gpt4 book ai didi

Python 在第二次发送之前不会检测到已关闭的套接字

转载 作者:太空狗 更新时间:2023-10-29 16:56:55 25 4
gpt4 key购买 nike

当我关闭连接一端的套接字时,另一端在第二次发送数据时出错,而不是第一次:

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", 12345))
server.listen(1)

client = socket.create_connection(("localhost",12345))
sock, addr = server.accept()
sock.close()

client.sendall("Hello World!") # no error
client.sendall("Goodbye World!") # error happens here

我试过设置 TCP_NODELAY,使用 send 而不是 sendall,检查 fileno(),我找不到任何方法让第一个发送抛出错误,甚至在之后检测到它失败了。 编辑:sock.close 之前调用 sock.shutdown 没有帮助。 编辑 #2: 即使在关闭之后和写入之前添加 time.sleep 也没关系。 编辑 #3:检查 send 返回的字节数没有帮助,因为它总是返回消息中的字节数。

因此,如果我想检测错误,我能想到的唯一解决方案是在每个 sendall 后面加上一个 client.sendall(""),这将引发一个错误。但这似乎很老套。我使用的是 Linux 2.6.x,所以即使解决方案仅适用于该操作系统,我也会很高兴。

最佳答案

这是预期的,以及 TCP/IP API 的实现方式(因此它在几乎所有语言和所有操作系统上都是相似的)

简而言之,如果 send() 调用以某种方式无法将数据传送到另一端,则您无法保证 send() 调用直接返回错误。 send/write 调用只是将数据传送到 TCP 堆栈,并且由 TCP 堆栈在可能的时候传送数据。

TCP 也只是一个传输协议(protocol),如果您需要知道您的应用程序“消息”是否已经到达另一端,您需要自己实现它(某种形式的 ACK),作为您的应用程序协议(protocol)的一部分 - 没有其他免费午餐。

但是 - 如果你从一个套接字中读取(),你可以在错误发生时立即得到通知,或者当另一端关闭套接字时 - 你通常需要以某种形式的多路复用事件循环(即,使用选择/轮询或其他一些 IO 多路复用工具)。

请注意,您不能从套接字中读取()来了解最近的发送/写入是否成功,这里有一些案例说明原因(但这是人们没有想到的总能得到您的案例)

  • 几个 write() 调用由于网络拥塞而被缓冲,或者因为 tcp 窗口关闭(可能是一个慢速读取器)然后另一端关闭套接字或发生硬网络错误,因此您无法判断if if 是最后一次未通过的写入,或者是您 30 秒前完成的写入。
  • 网络错误,或防火墙静静地丢弃您的数据包(没有生成 ICMP 回复),您将不得不等到 TCP 连接超时才能收到错误,这可能会持续很多秒,通常是几分钟。
  • 当您调用 send 时,TCP 正忙于进行重传 - 也许这些重传会产生错误。(实际上与第一种情况相同)

关于Python 在第二次发送之前不会检测到已关闭的套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4899593/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com