为什么Python的socket.recv()不会返回-1

时间:2019-11-10 16:45:48

标签: python sockets recv

如果在客户端进行s.recv_into()循环时关闭服务器套接字,我将无限地从recv_into()获得0。

据我了解,知道套接字已关闭的唯一方法不是通过Python套接字机制本身,而是使用select / poll / etc。

当套接字另一侧关闭时不返回-1的原理是什么?为什么我不能正确地区分“当前没有数据”和“现在没有数据”?

编辑:

也许正确的问题是-如果另一端终止了连接,为什么在使用recv()时没有抛出异常?

2 个答案:

答案 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(或任何其他语言)无法知道这一点。