使用netpipes/netcat绑定端口

3

我正在尝试编写一个简单的Bash脚本,它在监听端口,并用一个简单的HTTP响应进行回复。我的具体问题是,我不确定端口是否可用,如果绑定失败,我会一直尝试下一个端口,直到绑定成功。

到目前为止,我认为最容易实现这个功能的方式是:

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

我在这里使用的是来自Ubuntu软件包中的netpipesfaucet

问题在于,如果我只是将“test”打印到输出中,curl会抱怨非标准的HTTP响应(错误代码18)。这是公平的,因为我没有打印HTTP兼容的响应。

如果我用echo -ne "HTTP/1.0 200 OK\r\n\r\ntest"替换echo test,curl仍然会抱怨:

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

我认为问题出在faucet打印响应和处理连接的方式上。例如,如果我在服务器端使用netcat,那么curl就能正常工作:

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:$

我很乐意在我的主脚本中用netcat代替faucet,但问题是我想生成一个独立的服务器进程,以便能够从同一个基础shell运行客户端。faucet有一个非常方便的--daemon参数,因为它分叉到后台,我可以使用$?(退出状态码)来检查绑定是否成功。如果我想使用netcat实现类似的目的,我将不得不使用&进行分叉,而$?将无法工作。
有人知道为什么在这种特殊情况下faucet没有正确响应吗?或者能否提出解决这个问题的建议。我既没有与faucet也没有与netcat结婚,但希望使用bash或其实用程序实现解决方案(而不是编写其他脚本语言,如Perl或Python)。

1
(()) 中不需要使用 $(()): for (( i=PORT_BASE; i < PORT_BASE+PORT_RANGE; i++ ))。您还应该在 faucet 命令中使用 printf,因为 -n-e 选项的支持取决于 echo 的实现。通过 Wireshark 监视流量,我看到 faucet 出于某种原因发送了 RST - Dennis Williamson
感谢您的建议,我会根据您的评论修改我的脚本。 - mindas
4个回答

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

功能正常。问题似乎在于echo不知道如何正确地shutdown套接字,只使用close,而curl不满意从recvfrom中获得-1(无序关闭)而不是0(有序关闭)。

尝试使用socat,它会在子进程完成后继续清理。

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

2
也许您可以看看Richard Stevens的"sock"程序,它具有以下特点:
-F    fork after connection accepted   (TCP concurrent server)

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

同时,你也可以使用Bash命令:

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

谢谢,这听起来就是我需要的,虽然我已经让水龙头解决方案工作了。 - mindas

1

你真的需要使用HTTP协议吗?还是只是为了取悦curl?如果是后者,可以简单地合并。

 faucet $port --out --daemon echo test

使用

 hose $server $port --in cat

是的,我需要使用HTTP,因为最终目标是进行HTTP代理监控。 - mindas

1

感谢您的建议,但除非我误读了它们的手册页面,否则tcpserver和ncat都不比netcat更好(在我的情况下)。我提出问题的目的是为了理解为什么“faucet”无法响应,或者有一种不需要从bash分叉(像“faucet”一样而不是netcat)的替代方法,以便我可以检查进程状态。 - mindas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接