当我关闭连接一端的套接字时,另一端在第二次发送数据时出错,但不是第一次:
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
我尝试使用send
代替sendall
来设置TCP_NODELAY,检查fileno()
,我找不到任何方法来获取第一个发送错误甚至是之后发现它失败了。 编辑:在sock.shutdown
之前调用sock.close
无效。 编辑#2:甚至在结束之后和写作之前添加time.sleep
并不重要。 编辑#3:检查send
返回的字节数没有帮助,因为它总是返回消息中的字节数。
因此,如果我想检测错误,我可以提出的唯一解决方案是使用sendall
跟随每个client.sendall("")
,这会引发错误。但这似乎很苛刻。我在Linux 2.6.x上,所以即使解决方案只适用于该操作系统,我也会很高兴。
答案 0 :(得分:13)
这是预期的,以及如何实现TCP / IP API(所以它几乎在所有语言和所有操作系统上都相似)
简短的说法是,如果send()调用以某种方式无法将数据传递到另一端,则无法保证send()调用直接返回错误。发送/写入调用只是将数据传递到TCP堆栈,并且由TCP堆栈决定是否可以提供数据。
TCP也只是一种传输协议,如果您需要知道您的应用程序“消息”是否到达另一端,您需要自己实现(某种形式的ACK),作为应用程序协议的一部分 - 没有其他免费午餐。
但是 - 如果你从套接字中读取(),你可以在发生错误时立即得到通知,或者当另一端关闭套接字时 - 你通常需要在某种形式的多路复用事件循环中这样做(即,使用select / poll或其他IO多路复用工具)。
请注意,您无法从套接字中读取()以了解最近的发送/写入是否成功,以下是几个案例的原因(但是这是一个没有想到的情况总能得到你)
send
时,TCP正忙于重新传输 - 可能这些重新传输会产生错误。(与第一种情况完全相同)答案 1 :(得分:1)
根据docs,请在致电sock.shutdown()
之前致电sock.close()
。