socket.recv(recv_size) 什么时候返回?

73 投票
3 回答
208773 浏览
提问于 2025-04-17 00:15

通过测试,我得出结论,在以下三种情况下,socket.recv(recv_size) 会返回数据。

  1. 当连接关闭后。例如,客户端调用了 socket.close(),或者出现了任何套接字错误,这时会返回一个空字符串。

  2. 有一些数据到达,数据的大小超过了 recv_size

  3. 有一些数据到达,数据的大小小于 recv_size,并且在短时间内没有更多数据到达(我发现0.1秒就可以)。

关于第3点的更多细节:

#server.py

while True:
    data = sock.recv(10)
    print data, 'EOF'

#client1.py

sock.sendall("12345")
sock.sendall("a" * 50)

#client2.py

sock.sendall("12345")
time.sleep(0.1)
sock.sendall("a" * 50)

当我运行 client1.py 时,server.py 返回:

12345aaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaa EOF

当我运行 client2.py 时,server.py 返回:

12345 EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF

我的结论正确吗?我在哪里可以看到关于第3点的官方说明?

3 个回答

2

我觉得你的结论是对的,但不够准确。

根据文档的说明,socket.recv 主要是关注网络缓冲区的。

当套接字处于阻塞状态时,socket.recv 会在网络缓冲区有数据时返回。如果网络缓冲区里的数据量超过了 socket.recv 能处理的最大值,它就会返回它能处理的最大字节数。如果网络缓冲区里的数据量少于 socket.recv 能处理的最大值,它就会返回网络缓冲区里的所有数据。

4

它的行为和底层的 recv 函数是一样的。你可以查看这个 手册页面,里面有官方的行为描述(或者你也可以阅读一个更 通俗的描述,关于套接字 API 的内容)。

53

是的,你的结论是对的。socket.recv 是一个阻塞调用。

socket.recv(1024) 最多会读取1024个字节,如果没有数据可以读取,它会一直等着。如果你没有读取完所有的数据,下一次调用 socket.recv 就不会再阻塞了。

如果连接关闭了或者出现了错误,socket.recv 也会返回一个空字符串。

如果你想要一个非阻塞的socket,可以使用select模块(这比单纯使用socket要复杂一些),或者你可以使用 socket.setblocking

我以前在使用 socket.setblocking 时遇到过问题,但如果你想试试,可以随便用。

撰写回答