什么原因导致管道错误?

Jay*_*Jay 75 c broken-pipe

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

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

例如:

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

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

Jon*_*ler 53

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

  • @varevarao:我不认为排队传输和以特定间隔发送是一种解决方法.如果您的应用程序可以忍受延迟,那么排队传输直到超过要发送的MTU可能是一种解决方法. (4认同)
  • MTU:https://en.wikipedia.org/wiki/Maximum_transmission_unit (3认同)

Vik*_*exe 9

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

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

发送手册页也证实了这一点:

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

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

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


Joe*_*oel 6

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

编辑:

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