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

C 是什么导致管道破裂错误?,c,broken-pipe,C,Broken Pipe,我知道当对等端的套接字关闭时会抛出断管错误 但是,在我的测试中,我注意到,当对等端关闭时,在该端上的立即“发送”调用并不总是导致断管错误 例如: 在关闭对等端的套接字后(我通过调用close尝试了完全关闭,也通过杀死对等端尝试了异常关闭),如果我尝试发送40个字节,那么我不会得到断开的管道,但是,如果我尝试发送40000个字节,那么它会立即给出断开的管道错误 究竟是什么原因导致管道破裂,并且可以预测其行为?可能40个字节适合管道缓冲区,而40000个字节不适合 编辑: 当您尝试写入封闭管道时,发

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

但是,在我的测试中,我注意到,当对等端关闭时,在该端上的立即“发送”调用并不总是导致断管错误

例如:

在关闭对等端的套接字后(我通过调用close尝试了完全关闭,也通过杀死对等端尝试了异常关闭),如果我尝试发送40个字节,那么我不会得到断开的管道,但是,如果我尝试发送40000个字节,那么它会立即给出断开的管道错误


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

可能40个字节适合管道缓冲区,而40000个字节不适合

编辑:


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

观察网络关闭可能需要一些时间-在关闭后,总时间名义上约为2分钟(是的,分钟!),然后将发送到端口的数据包全部假定为死数据包。在某个点检测到错误情况。通过一次小的写操作,您就在系统的MTU内,因此消息将排队等待发送。如果写入量很大,则您比MTU更大,系统会更快地发现问题。如果忽略SIGPIPE信号,则函数将在检测到连接断开时的某个点返回断开管道上的EPIPE错误。

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

当您发送更大的数据块时,send调用进入阻塞状态

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

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

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


使用上述信息很难预测准确的场景,但我相信,这应该是您出现问题的原因。

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

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


(RHEL 7,打印机是理光品牌,HP配置是预先存在的,在以前的网络上可以正常工作)

@varevarao:我不认为将传输排队并按特定间隔发送是一种解决方法。如果您的应用程序能够承受延迟,将传输排队直到有超过MTU发送可能是一种解决方法。我认为这与ACK活动观察到的套接字的当前状态密切相关。Keepalive只是一个次要的源确认活动,默认情况下处于关闭状态。