造成管道破裂错误的原因是什么?

发布于 2024-10-10 06:41:03 字数 259 浏览 0 评论 0原文

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

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

例如:

关闭对等端的套接字后(我尝试通过调用 close 进行干净关闭,也尝试通过终止对等方进行异常关闭),如果我尝试发送 40 个字节,那么我不会得到损坏的管道,但是,如果我尝试发送 40000 字节,然后它立即给出损坏的管道错误。

到底是什么原因导致管道破裂?它的行为可以预测吗?

I know that broken pipe error is thrown when the socket on the peer side is closed.

But, in my test I have noted that an immediate 'send' call on this side when the peer side is closed doesn't always lead to a broken pipe error.

E.g.:

After closing the socket on peer side (I have tried clean closing by calling close and also abnormal closing by killing the peer), if I try to send 40 bytes, then I don't get a broken pipe, but, if I try to send 40000 bytes then it immediately gives broken pipe error.

What exactly causes broken pipe and can it's behavior be predicted?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

巷子口的你 2024-10-17 06:41:03

观察网络关闭可能需要一些时间 - 总时间名义上约为 2 分钟(是的,几分钟!),关闭后,发往端口的数据包都被假定为已失效。在某个时刻检测到错误情况。对于小写入,您位于系统的 MTU 之内,因此消息会排队等待发送。对于大写入,您的数据比 MTU 更大,系统会更快地发现问题。如果忽略 SIGPIPE 信号,则函数将在检测到连接损坏时的某个时刻在损坏的管道上返回 EPIPE 错误。

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.

素手挽清风 2024-10-17 06:41:03

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

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

send 手册页也证实了这一点:

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

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

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

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.

嘿嘿嘿 2024-10-17 06:41:03

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

编辑:

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

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.

浊酒尽余欢 2024-10-17 06:41:03

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

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.

初心未许 2024-10-17 06:41:03

会话超时设置可能是管道破裂的原因。

例如:服务器会话超时为 3 小时,负载均衡器为 1 小时。

负载均衡器在 1 小时后阻塞,但服务器继续发送响应。在这种情况下,管道的一端断裂。

但这也可以是一种用户行为。用户在下载等过程中关闭页面。

Session timeout settings may be the reason of broken pipe.

For example: Server session timeout 3 hours and load balancer has 1 hour.

Load balancer blocks after 1 hour, but server keeps sending response. In this case, one end of the pipe is broken.

But it can be also a user behavior. User closes the page during download etc.

心碎的声音 2024-10-17 06:41:03

您不需要通过网络发送代码来获取此错误。例如,这段 Python 3 代码(现在是我最喜欢的一段代码):

while 1:print()

将打印大量换行符,最终会引发 BrokenPipeError 。因此,如果向 IO 或其他流写入过多数据,就会收到此错误。

You do not need to send code through a network to get this error. For example, this Python 3 code (now my favourite piece of code):

while 1:print()

will print a lot of newlines, and eventually a BrokenPipeError will be raised. So you will get this error if you write too much data to an IO or other stream.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文