C语言 是什么导致断管错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4584904/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What causes the Broken Pipe Error?
提问by Jay
I know that broken pipe error is thrown when the socket on the peer side is closed.
我知道当对等端的套接字关闭时会抛出管道损坏错误。
But, in my test I have noted that an immediate 'send' call on this side when the peer side is closed doesn't always lead to a broken pipe error.
但是,在我的测试中,我注意到当对等端关闭时,在这一端立即“发送”调用并不总是导致管道损坏错误。
E.g.:
例如:
After closing the socket on peer side (I have tried clean closing by calling close and also abnormal closing by killing the peer), if I try to send 40 bytes, then I don't get a broken pipe, but, if I try to send 40000 bytes then it immediately gives broken pipe error.
在对等端关闭套接字后(我尝试通过调用 close 进行干净关闭,并通过杀死对等端进行异常关闭),如果我尝试发送 40 个字节,那么我不会收到损坏的管道,但是,如果我尝试发送 40000 字节然后它立即给出损坏的管道错误。
What exactly causes broken pipe and can it's behavior be predicted?
究竟是什么导致了管道破裂,它的行为可以预测吗?
采纳答案by Jonathan Leffler
It can take time for the network close to be observed - the total time is nominally about 2 minutes (yes, minutes!) after a close before the packets destined for the port are all assumed to be dead. The error condition is detected at some point. With a small write, you are inside the MTU of the system, so the message is queued for sending. With a big write, you are bigger than the MTU and the system spots the problem quicker. If you ignore the SIGPIPE signal, then the functions will return EPIPE error on a broken pipe - at some point when the broken-ness of the connection is detected.
观察网络关闭可能需要一些时间 - 总时间名义上是关闭后大约 2 分钟(是的,几分钟!),然后假定发往该端口的数据包都已死亡。在某个时刻检测到错误情况。通过少量写入,您位于系统的 MTU 内,因此消息将排队等待发送。大写,你比 MTU 大,系统可以更快地发现问题。如果您忽略 SIGPIPE 信号,则函数将在损坏的管道上返回 EPIPE 错误 - 在检测到连接损坏的某个时刻。
回答by Vikram.exe
The current state of a socket is determined by 'keep-alive' activity. In your case, this is possible that when you are issuing the sendcall, the keep-aliveactivity tells that the socket is active and so the sendcall will write the required data (40 bytes) in to the buffer and returns without giving any error.
套接字的当前状态由“保持活动”活动决定。在您的情况下,这可能是在您发出send调用时,keep-alive活动告诉套接字处于活动状态,因此send调用会将所需的数据(40 个字节)写入缓冲区并返回而不会出现任何错误。
When you are sending a bigger chunk, the send call goes in to blocking state.
当您发送更大的块时,发送调用进入阻塞状态。
The send man page also confirms this:
发送手册页也证实了这一点:
When the message does not fit into the send buffer of the socket, send() normally blocks, unless the socket has been placed in non-blocking I/O mode. In non-blocking mode it would return EAGAIN in this case
当消息不适合套接字的发送缓冲区时,send() 通常会阻塞,除非套接字已置于非阻塞 I/O 模式。在非阻塞模式下,它会在这种情况下返回 EAGAIN
So, while blocking for the free available buffer, if the caller is notified (by keep-alive mechanism) that the other end is no more present, the send call will fail.
因此,在阻塞空闲可用缓冲区时,如果(通过保持活动机制)通知调用者另一端不再存在,则发送调用将失败。
Predicting the exact scenario is difficult with the mentioned info, but I believe, this should be the reason for you problem.
使用上述信息很难预测确切的场景,但我相信,这应该是您遇到问题的原因。
回答by Joel
Maybe the 40 bytes fits into the pipe buffer, and the 40000 bytes doesn't?
也许 40 个字节适合管道缓冲区,而 40000 个字节不适合?
Edit:
编辑:
The sending process is sent a SIGPIPE signal when you try to write to a closed pipe. I don't know exactly when the signal is sent, or what effect the pipe buffer has on this. You may be able to recover by trapping the signal with the sigaction call.
当您尝试写入关闭的管道时,发送进程会收到一个 SIGPIPE 信号。我不知道什么时候发送信号,或者管道缓冲区对此有什么影响。您可以通过使用 sigaction 调用捕获信号来恢复。
回答by kingkong
When peer close, you just do not know whether it just stop sending or both sending and receiving.Because TCP allows this, btw, you should know the difference between close and shutdown. If peer both stop sending and receiving, first you send some bytes, it will succeed. But the peer kernel will send you RST. So subsequently you send some bytes, your kernel will send you SIGPIPE signal, if you catch or ignore this signal, when your send returns, you just get Broken pipe error, or if you don't , the default behavior of your program is crashing.
当 peer close 时,你只是不知道它是停止发送还是同时发送和接收。因为 TCP 允许这样做,顺便说一句,你应该知道 close 和 shutdown 之间的区别。如果 peer 都停止发送和接收,首先你发送一些字节,它会成功。但是对等内核会向您发送 RST。因此,随后您发送一些字节,您的内核将向您发送 SIGPIPE 信号,如果您捕获或忽略此信号,当您的发送返回时,您只会收到 Broken pipe 错误,否则,您的程序的默认行为是崩溃.
回答by Andy T
We had the Broken Pipe error after a new network was put into place. After ensuring that port 9100 was open and could connect to the printer over telnet port 9100, we changed the printer driver from "HP" to "Generic PDF", the broken pipe error went away and were able to print successfully.
在新网络安装到位后,我们遇到了 Broken Pipe 错误。在确保端口 9100 已打开并且可以通过 telnet 端口 9100 连接到打印机后,我们将打印机驱动程序从“HP”更改为“Generic PDF”,管道损坏错误消失并能够成功打印。
(RHEL 7, Printers were Ricoh brand, the HP configuration was pre-existing and functional on the previous network)
(RHEL 7,打印机为 Ricoh 品牌,HP 配置在以前的网络上已存在且功能正常)

