如何使nc
OS X Mavericks 上的客户端保持套接字打开并读取数据,直到服务器断开套接字?
我想通过将数据发送到服务器nc
,然后使用响应。问题是nc
在发送数据后断开套接字,而不等待服务器的响应。
这只会写入数据然后退出:
$ echo "my instruction here" | nc 127.0.0.1 $MY_PORT
这将写入数据,然后即使服务器已断开连接也不会退出:
$ cat <(echo "my instruction here") - | nc 127.0.0.1 $MY_PORT
OS X Mavericks 上的手册页nc
有以下用于发送HTTP GET
请求和打印响应的示例,但它不起作用。它只是发送请求然后退出,而不等待服务器的响应。手册页的信息似乎不正确?
$ echo -n "GET / HTTP/1.0\r\n\r\n" | nc host.example.com 80
答案1
nc 的默认行为是在 stdin 关闭时关闭连接。要进行更改,您可以在 Linux 上使用 -q 选项(如-q -1
),在 OS X 上可能是相同的。有关详细信息,请参阅手册页。
编辑:看起来 OS X nc 不支持 -q 开关或类似的东西。在这种情况下,您需要通过执行以下操作来确保 stdin 不会关闭:
(回显“foo”;睡眠100000)|数控...
答案2
一旦监听nc
(服务器)关闭,客户端nc
也会退出。
在 Mac OS X 上,您可以open -a 'Activity Monitor'
验证这一点。
该示例挂起的原因nc & cat
不是nc
,而是cat
继续保持其 stdin 和 stdout 打开以供读取和写入。
但是,当在监听关闭cat
后尝试写入管道时,会引发并终止。nc
SIGPIPE
cat
# cat & SIGPIPE test
(sleep 1; echo hi) |
(trap 'echo "received signal $(($? - 128))" 1>&2' EXIT; cat) | :
kill -l 13
man bash | less -p 'EXIT STATUS'
man bash | less -Ip '128\+n'
作为 Niklas Berglund 解决方法的替代方案,可以捕获客户端退出nc
以杀死整个进程组,包括挂起cat
命令。
# console 1
# ctrl-c will "kill 0" entire process group sh -c '...'
nc -l 8080
# console 2
# script command (FreeBSD version) will implicitly run: man 2 setsid
# kill 0 will therefore only kill the entire process group sh -c '...'
# run in a script kill 0 would otherwise kill the entire script
# cf. also https://github.com/jerrykuch/ersatz-setsid
script -q /dev/null sh -c '
(echo "my instruction here"; cat) | (trap "kill 0" EXIT; nc 127.0.0.1 8080)
'
答案3
解决方法是继续向套接字写入内容 - 一旦无法写入数据nc
就会退出。
(echo -ne "GET / HTTP/1.0\r\n\r\n"; (while true; do echo -e "\n"; sleep 1; done)) | nc example.com 80
nc
这将每秒发送一次空行,直到nc
无法写入套接字并nc
退出。
感谢 Steffen Ullrich 的回答和评论指导我找到了这个解决方案。