如果在客户端进行s.recv_into()
循环时关闭服务器套接字,我将无限地从recv_into()
获得0。
据我了解,知道套接字已关闭的唯一方法不是通过Python套接字机制本身,而是使用select / poll / etc。
当套接字另一侧关闭时不返回-1的原理是什么?为什么我不能正确地区分“当前没有数据”和“现在没有数据”?
编辑:
也许正确的问题是-如果另一端终止了连接,为什么在使用recv()
时没有抛出异常?
答案 0 :(得分:1)
background-color:#FFFFFF;
只是名称为recv_into
的C系统调用的包装。 recv
的返回值不是错误的条件!
根据Linux手册,recv(2)
:
返回值
这些调用返回接收到的字节数,如果出错则返回-1 发生。如果发生错误,则将errno设置为指示 错误。
当流套接字对等方执行有序关闭时, 返回值将为0(传统的“文件结束”返回)。
各种域(例如UNIX和Internet)中的数据报套接字 域)允许零长度数据报。当这样的数据报是 收到,返回值为0。
如果请求的字节数也可能返回值0 从流套接字接收的数据为0。
对于错误情况,Python不会返回0
,而是会引发适当的异常。
对于流套接字,只要-1
返回表示已接收到0字节的值,就必须中断循环。没有必要检查recv_*
,但是如果您确实想确定一点,可以自然使用-1
或类似的方法。
Python中的各种while sock.recv_into(....) > 0:
调用都以类似的方式工作。
答案 1 :(得分:1)
如果在客户端进行
s.recv_into()
循环时关闭服务器套接字,我将无限地从recv_into()
获得0。
是,正如预期的那样。闭合的连接用0而不是-1表示。
据我了解,知道套接字已关闭的唯一方法不是通过Python套接字机制本身,而是使用select / poll / etc。
不,那不是事实。只需在非阻塞模式下调用recv
即可完成这项工作,而无需使用任何选择器机制。在非阻塞模式下,将通过适当的异常指示“尚无数据”状态(请注意,您必须检查该异常,这不是recv
抛出时的唯一情况)。
但是,这并不意味着对等方仍然处于活动状态(默认TCP超时为15分钟AFAIK)。这不能被可靠地检测到。最好的办法是通过导线实现一些ping协议。
当套接字另一侧关闭时不返回-1的原理是什么?
对于系统调用(例如recv
),-1返回码(通常)保留用于错误。但是Python将这些转换为异常(因此AFAIK在Python中永远不会得到-1)。
无论如何0都不是错误。这是另一侧关闭连接的信息。也许这是完全正确的情况,Python(或任何其他语言)无法知道这一点。