【问题标题】:Python 2.7 TCP Sockets: socket.send() that returns zero versus socket.send() that raises socket.error exception?Python 2.7 TCP 套接字:返回零的 socket.send() 与引发 socket.error 异常的 socket.send()?
【发布时间】:2013-10-12 02:36:07
【问题描述】:
来自http://docs.python.org/2/howto/sockets.html
如果一个 socket send 或 recv 在处理 0 个字节后返回,则
连接已断开。
另一方面,如果 TCP 连接的远程端关闭(或被杀死),并且随后调用了 socket.send(),则可以看到以下 socket.error 异常
socket.error: [Errno 104] 对等方重置连接
现在我的问题是,“connection has been broken”和“Connection reset by peer”有什么区别。 “连接已断开”的确切含义 == socket.send() 返回零。对我来说,即使是一个字符也无法发送,这与 socket.error 异常一样糟糕。无论导致 socket.send 返回零的事件,理想情况下都应该引发 socket.error 异常,这样应用程序就不必处理两个不同的事情(异常和返回值为零)。
【问题讨论】:
标签:
python
sockets
exception
python-2.7
error-handling
【解决方案1】:
获取 RST 是 TCP 协议中一个非常特殊的用例——对等方通过在 TCP 标头中设置 RST 标志来发回消息。这通常意味着对等方没有套接字端点。如果远程对等方的计算机突然重新启动而没有机会优雅地关闭套接字(也就是使用 4 路 FIN 消息),则可能会发生这种情况。一旦它重新上线,它就会丢失之前的套接字端点,如果它为旧连接接收到任何新的 TCP 数据包,那么它将通过设置 RST 标志来发送 TCP 消息。
与接收 RST 相反,连接可能由于其他原因而关闭。其中之一是使用 FIN 消息的正常优雅。在这种情况下,TCP 层的底层连接是关闭的。另一种情况可能是对等方的连接丢失并且设置了 TCP Keepalive 选项。对于这种情况,当对等体空闲时,TCP 将发送保活探测,并且由于不存在连接,因此不会对保活进行回复。一旦 TCP 层没有收到一组 N 个 keepalive,那么它将在本地关闭连接。在这样的套接字上调用 Python 的 send 和 recv 会返回 0。