断开连接后使netcat丢弃所有字节

Make netcat discard all bytes after disconnect

我通过 bash 使用 netcat 运行 一个微型开发网络服务器,它能够一次处理一个连接。

Netcat 启动如下(-k 使其在多个连接中存活):

nc -kl 3000

bash 脚本处理由 netcat 接收的浏览器请求,并构建响应,该响应通过同一 netcat 实例发送回浏览器。

一切都按预期工作,但有时,浏览器无法获得它请求的文件。我的怀疑:如果在响应完全发送之前关闭连接,则响应的其余部分将作为对以下请求的响应发送(当然,它不属于)。

证明

  1. 终端 1(服务器):nc -kl 3000
  2. 终端2(模拟浏览器): nc localhost 3000
  3. 在终端 1 中输入 hello\n
  4. 2 号航站楼打印 hello\n
  5. 在终端2按Ctrl+C结束连接。
  6. 在终端 1 中输入 world\n
  7. 运行 nc localhost 3000 再次在终端 2(新连接)。
  8. 终端 2 立即显示 world\n,即使 world\n 实际上是在不存在连接时发送的,这意味着第一个连接中的第二个响应行。

要求的行为:如果不存在连接,则忽略传递给 netcat 的所有字节。

是否可以使用netcat? (我更喜欢像 netcat 这样的工具,因为它预装在所有机器上。)

嗯,作为一种解决方法,如果你能做到这一点,而不是 运行ning ncat 使用保持打开选项,只需在 while 循环中的每个连接之间重新生成它:

while true; do
    #what you want to do with: ncat -l 3000 
done

然后每次进程重新生成时,它会丢弃所有标准输入,然后您从下一个 i/o 开始下一个进程。

当然,如果重新生成您的 bash 脚本不方便,那么这可能意味着您没有使用正确的工具来完成这项工作。 (您也许可以解决使用 fifos 或使用临时 fds 的问题,但为了避免使用更适合该工作的语言编写脚本,这会过度设计)。


如果您还没有这样做,您是否尝试过从 netcat 中 运行ning 脚本而不是相反?

ncat -kl 3000 -c ./script.sh

它将为每个连接生成脚本,并在该连接上重定向 stdin/stdout。然后当客户端断开连接时,脚本将被终止并且应该释放你的输入fd。

实际上,如果您将文件作为 HTTP 服务器提供,您可能需要查找:

ncat -lk 3000 --lua-exec httpd.lua

httpd.lua offered with the ncat distribution


如果您想要一个简单的 运行 anywhere 脚本在您的系统上执行某些操作,您可以编写一个小的 python 脚本。

它默认安装在 ubuntu(以及许多其他系统)上,并且您提供了一个极简主义的 Web 服务器实现,例如用于提供您刚刚执行的文件:

python -m SimpleHTTPServer <port>

easy to customize 更适合您的独特需求,并且可以让您完全控制套接字和文件描述符。

坚持需要 "run everywhere" 脚本,您可以尝试逐行处理输入并检测是否存在 ESTABLISHED 连接 netstat:

while read line; do 
  netstat -an | grep 3000 | grep -q ESTABLISHED; 
  ret=$?; 
  if [ "$ret" == "0" ]; then 
    echo $line; 
  else 
    # this output is just for fun, and can be removed
    echo "not sending $line" >&2; 
  fi; 
done | nc -kl 3000

这将有基于线路的限制,如果连接在 netstat 调用后立即关闭,仍然可能错误地向 netcat 发送数据。这两个 grep 调用应该确保您不会错误地检测到您自己的 grep。

我尝试寻找连接关闭时 netcat 返回的信号,但看不到任何暴露给 shell 的信号。

使用 fifo 可以证明 netcat 保持其 stdin 打开,即使在不存在连接时也是如此:

mkfifo test

nc -kl < test

# then in a different shell
for a in {0..5}; do echo hi > test; done

for 不会阻塞,因此 netcat 正在主动读取标准输入但对其进行缓冲(我看不到关闭缓冲的选项)。这意味着除了查看网络状态外,您无法真正区分 netcat 是否具有活动连接。 netstat 是获取此状态的众多方法之一。