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

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

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

例如:

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

究竟是什么原因导致了管道的断裂,管道的断裂行为是否可以预测?

369745 次浏览

Maybe the 40 bytes fits into the pipe buffer, and the 40000 bytes doesn't?

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.

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.

The current state of a socket is determined by 'keep-alive' activity. In your case, this is possible that when you are issuing the send call, the keep-alive activity tells that the socket is active and so the send call will write the required data (40 bytes) in to the buffer and returns without giving any error.

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

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.

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.