After reading article https://www.xmodulo.com/tcp-udp-socket-bash-shell.html, I tried to write a simple script:
#!/bin/bash
exec 3<>/dev/tcp/time.nist.gov/13
for i in {1..3}; do
echo -e "GET / HTTP/1.1\r\nhost: service\r\nConnection: close\r\n\r\n" >&3
cat <&3
echo "get sent"
sleep 10
done
exec 3<&-
echo "done"
It successfully returned me the time but then only "Bad file descriptor".
But if I move the opening and the opening of file descriptor 3, it runs fine
#!/bin/bash
for i in {1..3}; do
exec 3<>/dev/tcp/time.nist.gov/13
echo -e "GET / HTTP/1.1\r\nhost: service\r\nConnection: close\r\n\r\n" >&3
cat <&3
echo "get sent"
exec 3<&-
sleep 10
done
echo "done"
Why is that?
(I'd prefer to keep the TCP socket open without closing and re-opening it.)
Port 13 is the daytime protocol, which is not HTTP. Thus sending a HTTP request to the server is wrong in the first place. Instead one must follow the specification of the daytime protocol - see Wikipedia: Daytime Protocol for an overview.
Basically the protocol works by doing a connect to the server and reading until connection close - the client does not send any application data at all. Since one must read until connection close and there is no concept of a "request" one also cannot keep the connection open for more "requests". Instead a new connection must be created for each new query.
for i in {1..3}; do
exec 3<>/dev/tcp/time.nist.gov/13
cat <&3
exec 3<&-
sleep 10
done
echo "done"
But even if the other side would be an HTTP server the tried approach will not work. For one: the HTTP request explicitly asks for Connection: close
, thus excluding multiple requests on the same connection. And, the cat <&3
reads until connection close by the server instead of HTTP response end, which makes getting multiple responses on the same connection and thus also multiple requests impossible too.