使用socket.recv()时,程序在没有更多数据可读时挂起

2 投票
2 回答
9604 浏览
提问于 2025-04-18 18:30

我正在接收一串二进制消息。每条消息都有一个ID和长度,我是根据这些信息来解析消息的。我想读取所有发送过来的消息;但是,如果我尝试接收的字节数超过了实际发送的字节数,程序就会卡住,直到之前设置的socket.settimeout()超时。

我希望这样来处理:

while end_of_file == 0:
    header = socket.recv(6)
    if header == '':
        end_of_file = 1

这个方法不行,因为它总是期待再接收6个字节。

2 个回答

2

客户端不会知道服务器没有发送更多数据,除非服务器主动告诉它。这意味着:

  • 要么服务器提前告诉客户端预计会有多少数据
  • 要么服务器会发送一些特殊的数据,来表示没有更多数据了
  • 要么服务器可以关闭连接,这也表示没有更多数据会来了(也就是说,recv会返回)。注意,这种方法只适用于有连接的情况,比如TCP,而不适用于UDP。
3

你自己说过:

如果我尝试接收比发送的更多的字节,程序就会卡住。

你描述的情况是正常的行为,特别是在套接字处于阻塞模式下(这是默认设置)。你告诉它去读取数据,它就会一直等到有新数据到来。

如果你不想让它一直等下去,你可以选择:

  1. 调用 socket.settimeout(),然后在读取时处理可能出现的 timeout 异常。

  2. 使用 select.select() 来检测套接字是否有待读取的数据,然后再调用 socket.recv() 来读取数据。

撰写回答