cnt=0
while true; do
let cnt++
resp=$"<h1>Simple webserver</h1>My PID is <code>$$<</code>p>Request counter: <code>$cnt</code>"
len="$(printf '%s' "$resp" | wc -c)"
printf "HTTP/1.1 200 OK\r\nContent-Encoding: text/html\r\nContent-Length: $len\r\n\r\n<h1>Simple Webserver</h1>My PID is <code>$$</code><p>Request counter is <code>$cnt</code>" | nc -Nl 8000
done
The -N option specifies that the socket is shutdown when it receives an EOF on the input. The man page says that «some servers require this to finish their work».
In an Oracle Linux environment, I found nc to be ncat (readlink -f /usr/bin/nc returned /usr/bin/ncat) which does not understand the -N option. In this environment, replacing -Nl8000 with -l 8000 --send-only did the job.
Also note that the request counter ($cnt) increases by two if the webserver is accessed with a traditional web browser because the browser also tries to fetch /favicon.ico.
Test client server
nc can be used to rudimentarily test a client-server scenario.
In a shell, the «server» is started using -l to indicate the port where the server is listening. -q 1 tells the server to quit if it doesn't receieve any input from a client within 1 second after delivering the message (here: «hello from server):
$ echo 'hello from server' | nc -l 1234 -q 1
After the server is started, a client is started in another shell that connects to port 1234, then prints the message received from the server and then delivers another message («this is the client») to the server:
$ echo 'this is the client' | nc localhost 1234 -q 1
hello from server
Going back the first shell, we see the server having printed the message from the client:
this is the client
Print a browser's HTTP request headers
nc -kdl 8000
Slow HTTP Request
The following example sends the header of a HTTP request but then waits 2 minutes for the terminating empty line.