在我的 Raspberry Pi 3 终端(Linux)上,我输入了以下内容并点击Enter:
printf 'HTTP/1.1 302 Moved\r\nLocation: https://www.eff.org/' | nc -l 2345
Raspberry Pi 3 是我家庭网络的一部分,固定地址为 192.168.0.8。然后,我在 Mac 上的浏览器 (Chrome) 中输入以下内容并点击Enter:
192.168.0.8:2345
我可以在我的 Linux 终端(Raspberry Pi)上看到浏览器的 GET 请求,但是nc
监听器卡住了并且没有将答复(HTTP 302 重定向消息)发送到浏览器。
仅当我nc
通过点击Ctrl+停止程序时C,浏览器才会收到回复消息并显示https://www.eff.org
网站。
有谁知道为什么nc
监听器卡住了而不是发送答复并关闭连接?
答案1
我复制了您的问题。当我使用另一个nc
浏览器而不是浏览器进行连接时,我看到回复正在立即发送。我认为您的浏览器也收到了回复,但由于nc
没有终止连接,浏览器不知道这一切,因此可以继续重定向。
\r\n
(注意:在我的测试中,我需要回复中的最后一个nc
才能成功重定向我的浏览器,因此我所有的示例都使用此修复程序。)
编辑:简单修复
这里我发现了以下情况:
HTTP 请求和 HTTP 响应使用 RFC 822 的通用消息格式来传输所需的数据。该通用消息格式由以下四项组成。
- [...]
- [...]
- 一个空行(即 CRLF 之前没有任何内容的行),表示标头字段的结束
- [...]
所以你的答复应该是:
printf 'HTTP/1.1 302 Moved\r\nLocation: https://www.eff.org/\r\n\r\n' | ...
收到此信息后,您的浏览器应继续重定向,自行终止连接nc
。2017 年 12 月初,它适用于 Opera 和 Vivaldi;但不适用于 Firefox、Chrome 或 Safari,您可能需要其他修复程序(见下文)。
原来的,现在较差的答案(对于非 HTTP 通信可能仍然有用nc
)
根据Server Fault 上的这个答案您需要使用-c
或-q
类似选项,具体取决于nc
实施。
在我的 Debian 中,我-q
安装了可用的版本。然后
printf 'HTTP/1.1 302 Moved\r\nLocation: https://www.eff.org/\r\n' | nc -q 0 -l -p 2345
工作正常(注意我还需要-p
指定端口)。解释如下:
-q seconds
EOF
on 后stdin
,等待指定的秒数然后退出。如果秒数为负数,则永远等待(默认)。
如果你nc
没有合适的选择,那么解决方法可能是检测来自客户端的通信并终止整个命令行。在我的 Debian 中可以运行的一个示例bash
是:
printf 'HTTP/1.1 302 Moved\r\nLocation: https://www.eff.org/\r\n' | nc -l -p 2345 | { read foo; sleep 1; kill 0; }
运行管道时,bash
将每个进程放在一个进程组中;kill 0
向其整个进程组发送信号。此方式nc
在收到触发的任何请求后约 1 秒内被终止read
。