什么原因导致管道错误?

时间:2011-01-03 13:39:49

标签: c broken-pipe

我知道当对端的套接字关闭时会抛出管道错误。

但是,在我的测试中,我注意到当对等方关闭时,此方立即发送“发送”呼叫并不总是导致管道错误。

E.g:

在对等端关闭套接字后(我通过调用close来尝试干净关闭,并且通过查杀对等体也尝试异常关闭),如果我尝试发送40个字节,那么我不会得到一个损坏的管道,但是,如果我尝试发送40000字节,然后立即发出管道错误。

究竟是什么原因导致管道断裂并且可以预测它的行为?

5 个答案:

答案 0 :(得分:46)

接近观察网络可能需要一段时间 - 在关闭之前,总计时间在名义上约为2分钟(是,分钟!),然后才会假定发往该端口的数据包已全部死亡。在某些时候检测到错误条件。使用小写时,您位于系统的MTU内,因此消息排队等待发送。通过大写,您比MTU更大,系统可以更快地发现问题。如果忽略SIGPIPE信号,那么函数将在断开的管道上返回EPIPE错误 - 在检测到连接断裂的某个时刻。

答案 1 :(得分:8)

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

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

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

  

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

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

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

答案 2 :(得分:3)

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

编辑:

当您尝试写入已关闭的管道时,发送过程将发送一个SIGPIPE信号。我不知道信号何时被发送,或者管道缓冲器对此有何影响。您可以通过使用sigaction调用捕获信号来恢复。

答案 3 :(得分:0)

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

答案 4 :(得分:-1)

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

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