+1 To 格雷格·休吉尔 https://stackoverflow.com/questions/2216374/why-is-writing-a-closed-tcp-socket-worse-than-reading-one/2216386#2216386引导我的思维过程朝着正确的方向寻找答案。
真正的原因是SIGPIPE
套接字和管道中的过滤器习惯用法/模式适用于 Unix 系统中的典型 I/O。
从管道开始。像 grep 这样的过滤程序通常会写入STDOUT
并从中读取STDIN
,它可以被 shell 重定向到管道。例如:
cat someVeryBigFile | grep foo | doSomeThingErrorProne
shell 当它分叉然后执行这些程序时可能使用dup2 http://linux.die.net/man/2/dup2系统调用重定向STDIN
, STDOUT
and STDERR
到适当的管道。
自过滤程序grep
不知道也无法知道它的输出已被重定向,那么告诉它停止写入损坏的管道的唯一方法是:doSomeThingErrorProne
崩溃是有信号的,因为写入的返回值STDOUT
很少被检查过。
带插座的模拟将是inetd http://en.wikipedia.org/wiki/Inetd服务器取代了 shell。
作为一个例子,我假设你可以转grep
进入一个网络服务,该服务运行于TCP
插座。例如与inetd
如果你想拥有一个grep
服务器开启TCP
端口 8000 然后将其添加到/etc/services
:
grep 8000/tcp # grep server
然后将其添加到/etc/inetd.conf
:
grep stream tcp nowait root /usr/bin/grep grep foo
Send SIGHUP
to inetd
并使用 telnet 连接到端口 8000。这应该会导致inetd
要分叉,请将套接字复制到STDIN
, STDOUT
and STDERR
然后执行grep
以 foo 作为参数。如果您开始在 telnet 中输入行grep
将回显那些包含 foo 的行。
现在用名为的程序替换 telnetticker
例如,将实时股票报价流写入STDOUT
并获取命令STDIN
。有人远程登录到端口 8000 并输入“start java”以获取 Sun Microsystems 的报价。然后他们起床去吃午饭。 telnet 莫名其妙地崩溃了。如果没有SIGPIPE
然后发送ticker
会永远不断地发送报价,永远不知道另一端的进程已经崩溃,并且不必要地浪费系统资源。