我知道当对等端的套接字关闭时会引发管道破裂错误。但是,在我的测试中,我注意到当对等端关闭时,在这一端立即调用"send"并不总是导致管道中断错误。例如:关闭对等端的套接字后(我尝试过通过调用close进行干净关闭,也尝试过通过杀死对等端进行异常关闭),如果我尝试发送40个字节,那么我不会得到一个破碎的管道,但是,如果我尝试发送40000个字节,那么它会立即给出破碎管道错误。究竟是什么原因导致管道破裂,它的行为可以预测吗?
5f0d552i1#
观察网络附近可能需要时间-总时间通常约为2分钟(是的,几分钟!)关闭后,发往该端口的数据包都被认为是死的。错误条件在某个点被检测到。使用小的写入,您在系统的MTU内,因此消息排队等待发送。使用大的写入,你比MTU大,系统能更快地发现问题。如果你忽略SIGPIPE信号,那么函数会在检测到连接断开时的某个点返回管道断开的EPIPE错误。
d6kp6zgx2#
套接字的当前状态由“keep-alive”活动决定。在您的情况下,当您发出send调用时,keep-alive活动告知套接字处于活动状态,因此send调用将所需的数据(40字节)写入缓冲区并返回,而不会给出任何错误。当您发送更大的块时,send调用进入阻塞状态。send手册页也证实了这一点:当消息不适合套接字的发送缓冲区时,send()通常会阻塞,除非套接字已被置于非阻塞I/O模式。在这种情况下,在非阻塞模式下,它将返回EAGAIN因此,在阻塞空闲的可用缓冲区时,如果呼叫者被通知(通过保活机制)另一端不再存在,则发送呼叫将失败。预测确切的情况是困难的与提到的信息,但我相信,这应该是你的问题的原因。
send
keep-alive
n7taea2i3#
也许40字节适合管道缓冲区,而40000字节不适合?编辑:当你试图写入一个关闭的管道时,发送进程会被发送一个SIGPIPE信号。我不知道信号是什么时候发送的,或者管道缓冲区对此有什么影响。你可以通过使用sigaction调用捕获信号来恢复。
jhkqcmku4#
当peer关闭时,你不知道它是停止发送还是同时停止发送和接收。因为TCP允许这样做,顺便说一句,你应该知道关闭和关机的区别。如果peer同时停止发送和接收,首先你发送一些字节,它会成功。但是peer内核会发送RST给你。所以随后你发送一些字节,你的内核会发送SIGPIPE信号给你。如果你捕捉到或者忽略了这个信号,当你的send返回时,你只会得到Broken pipe错误,或者如果你没有捕捉到,你的程序的默认行为是崩溃。
eh57zj3b5#
会话超时设置可能是管道损坏的原因。例如:* * 服务器会话超时3小时,***负载平衡器*超时1小时。负载平衡器在1小时后阻塞,但服务器继续发送响应。在这种情况下,管道的一端断开。但它也可以是一种用户行为,如用户在下载过程中关闭页面等。
5条答案
按热度按时间5f0d552i1#
观察网络附近可能需要时间-总时间通常约为2分钟(是的,几分钟!)关闭后,发往该端口的数据包都被认为是死的。错误条件在某个点被检测到。使用小的写入,您在系统的MTU内,因此消息排队等待发送。使用大的写入,你比MTU大,系统能更快地发现问题。如果你忽略SIGPIPE信号,那么函数会在检测到连接断开时的某个点返回管道断开的EPIPE错误。
d6kp6zgx2#
套接字的当前状态由“keep-alive”活动决定。在您的情况下,当您发出
send
调用时,keep-alive
活动告知套接字处于活动状态,因此send
调用将所需的数据(40字节)写入缓冲区并返回,而不会给出任何错误。当您发送更大的块时,send调用进入阻塞状态。
send手册页也证实了这一点:
当消息不适合套接字的发送缓冲区时,send()通常会阻塞,除非套接字已被置于非阻塞I/O模式。在这种情况下,在非阻塞模式下,它将返回EAGAIN
因此,在阻塞空闲的可用缓冲区时,如果呼叫者被通知(通过保活机制)另一端不再存在,则发送呼叫将失败。
预测确切的情况是困难的与提到的信息,但我相信,这应该是你的问题的原因。
n7taea2i3#
也许40字节适合管道缓冲区,而40000字节不适合?
编辑:
当你试图写入一个关闭的管道时,发送进程会被发送一个SIGPIPE信号。我不知道信号是什么时候发送的,或者管道缓冲区对此有什么影响。你可以通过使用sigaction调用捕获信号来恢复。
jhkqcmku4#
当peer关闭时,你不知道它是停止发送还是同时停止发送和接收。因为TCP允许这样做,顺便说一句,你应该知道关闭和关机的区别。如果peer同时停止发送和接收,首先你发送一些字节,它会成功。但是peer内核会发送RST给你。所以随后你发送一些字节,你的内核会发送SIGPIPE信号给你。如果你捕捉到或者忽略了这个信号,当你的send返回时,你只会得到Broken pipe错误,或者如果你没有捕捉到,你的程序的默认行为是崩溃。
eh57zj3b5#
会话超时设置可能是管道损坏的原因。
例如:* * 服务器会话超时3小时,***负载平衡器*超时1小时。
负载平衡器在1小时后阻塞,但服务器继续发送响应。在这种情况下,管道的一端断开。
但它也可以是一种用户行为,如用户在下载过程中关闭页面等。