Binding on a port with netpipes/netcat

懵懂的女人 提交于 2019-12-12 08:58:24

问题


I am trying to write a simple bash script that is listening on a port and responding with a trivial HTTP response. My specific issue is that I am not sure if the port is available and in case of bind failure I fall back to next port until bind succeeds.

So far to me the easiest way to achieve this was something like:

for (( i=$PORT_BASE; i < $(($PORT_BASE+$PORT_RANGE)); i++ ))
do
  if [ $DEBUG -eq 1 ] ; then
    echo trying to bind on $i
  fi
  /usr/bin/faucet $i --out --daemon echo test 2>/dev/null
  if [ $? -eq 0 ] ; then                        #success?
    port=$i
    if [ $DEBUG -eq 1 ] ; then
      echo "bound on port $port"
    fi
    break
  fi
done

Here I am using faucet from netpipes Ubuntu package.

The problem with this is that if I simply print "test" to the output, curl complains about non-standard HTTP response (error code 18). That's fair enough as I don't print HTTP-compatible response.

If I replace echo test with echo -ne "HTTP/1.0 200 OK\r\n\r\ntest", curl still complains:

user@server:$ faucet 10020 --out --daemon echo -ne "HTTP/1.0 200 OK\r\n\r\ntest"
...
user@client:$ curl ip.of.the.server:10020
curl: (56) Failure when receiving data from the peer

I think the problem lies in how faucet is printing the response and handling the connection. For example if I do the server side in netcat, curl works fine:

user@server:$ echo -ne "HTTP/1.0 200 OK\r\n\r\ntest\r\n" | nc -l 10020
...
user@client:$ curl ip.of.the.server:10020
test
user@client:$

I would be more than happy to replace faucet with netcat in my main script, but the problem is that I want to spawn independent server process to be able to run client from the same base shell. faucet has a very handy --daemon parameter as it forks to background and I can use $? (exit status code) to check if bind succeeded. If I was to use netcat for a similar purpose, I would have to fork it using & and $? would not work.

Does anybody know why faucet isn't responding correctly in this particular case and/or can suggest a solution to this problem. I am not married neither to faucet nor netcat but would like the solution to be implemented using bash or it's utilities (as opposed to write something in yet another scripting language, such as Perl or Python).


回答1:


faucet 10020 --out --daemon \
    echo -ne "HTTP/1.0 200 OK\r\nContent-Length: 4\r\n\r\ntest"

works fine. The issue seems to be that echo doesn't know how to properly shutdown a socket, using just close instead, and curl is unhappy about getting a -1 (disorderly shutdown) rather than a 0 (orderly shutdown) from recvfrom.

Try socat which sticks around to clean up after the child is done.

socat tcp-l:10020,fork,reuseaddr \
    exec:'echo -ne "HTTP/1.0 200 OK\r\n\r\ntest"'



回答2:


Maybe have a look at the "sock" program of Richard Stevens as well. It has:

-F    fork after connection accepted   (TCP concurrent server)

http://www.icir.org/christian/sock.html

And using Bash you may also use:

echo $'HTTP/1.0 200 OK\r\n\r\ntest\r\n'



回答3:


do you really need to use HTTP protocol, or is that just to please curl? if it's the latter, simply combine

 faucet $port --out --daemon echo test

with

 hose $server $port --in cat



回答4:


How about using the program called tcpserver from the DJB ucspi-tcp package.

http://lserinol.blogspot.com/2008/12/simple-tcp-server-with-djb-tcpserver.html

An advanced alternative to netcat or nc respectively is ncat (part of nmap).



来源:https://stackoverflow.com/questions/4634245/binding-on-a-port-with-netpipes-netcat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!