是什么原因导致管道破裂错误?


83

我知道关闭对等端的套接字时会引发管道破裂错误。

但是,在我的测试中,我注意到,当对等端关闭时,在此端立即进行“发送”调用并不总是会导致管道错误。

例如:

关闭对等端的套接字后(我尝试通过调用close进行干净关闭,也通过杀死对等体来异常关闭),如果我尝试发送40个字节,则管道不会断开,但是,如果我尝试发送40000字节,则立即给出管道中断错误。

究竟是什么原因导致管道破裂,并且可以预测其行为?

Answers:


59

观察网络可能要花费一些时间-在关闭之后,总的时间通常在关闭后大约2分钟(是的,几分钟!)之前,假定所有发往该端口的数据包都被视为已死亡。在某些时候检测到错误情况。只需很小的写入,您就位于系统的MTU中,因此消息已排队等待发送。大量写入时,您比MTU还要大,系统会更快地发现问题。如果您忽略SIGPIPE信号,则函数将在管道断开时返回EPIPE错误-在检测到连接断开的某个时候。


4
@varevarao:我认为对传输进行排队并在特定时间间隔发送不是解决方法。如果您的应用程序可以承受延迟,则对传输进行排队直到发送的MTU超过一个为止。
乔纳森·莱夫勒

11

套接字的当前状态由“保持活动”活动确定。在您的情况下,有可能在发出send调用时,keep-alive活动会告知套接字处于活动状态,因此send调用会将所需的数据(40字节)写入缓冲区,并返回而不会出现任何错误。

当您发送更大的块时,发送调用将进入阻塞状态。

发送手册页也确认了这一点:

当消息不适合套接字的发送缓冲区时,除非套接字已置于非阻塞I / O模式,否则send()通常会阻塞。在非阻塞模式下,在这种情况下它将返回EAGAIN

因此,在阻塞可用空闲缓冲区的同时,如果(通过保持活动机制)通知调用方另一端不再存在,则发送调用将失败。

使用上述信息很难预测出确切的情况,但是我相信,这应该是您遇到问题的原因。


1
通过ACK活动观察套接字的当前状态。Keepalive只是一个次要源ACK活动,默认情况下处于关闭状态。
罗恩侯爵,

3

也许40个字节适合管道缓冲区,而40000个字节不适合吗?

编辑:

当您尝试写入封闭的管道时,发送过程将发送SIGPIPE信号。我不知道何时发送信号,也不知道管道缓冲区对此有什么影响。您可以通过使用sigaction调用捕获信号来恢复。


0

当peer关闭时,您只是不知道它只是停止发送还是发送和接收。由于TCP允许这样做,顺便说一句,您应该知道close和shutdown之间的区别。如果对等方都停止发送和接收,则首先发送一些字节,它将成功。但是对等内核将向您发送RST。因此,随后发送一些字节,内核将向您发送SIGPIPE信号,如果您捕获或忽略了该信号,则在发送返回时,您将得到“ Broken Pipe”错误,否则,您的程序的默认行为将崩溃。


-1

建立新网络后,我们出现了管道破裂的错误。确保端口9100已打开并可以通过telnet端口9100连接到打印机后,我们将打印机驱动程序从“ HP”更改为“ Generic PDF”,断开的管道错误消失了,并且能够成功打印。

(RHEL 7,打印机是理光品牌,HP配置在先前的网络中已经存在并且可以使用)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.