python socket.recv()方法如何知道消息的结尾?

Tom*_*mmy 6 python sockets recv

假设我使用1024作为客户端套接字的缓冲区大小:

recv(1024)
Run Code Online (Sandbox Code Playgroud)

假设服务器要发送给我的消息包含2024个字节。我的套接字只能接收1024个字节。其他1000个字节又怎么了?

  1. recv方法是否会等待一定的时间(例如2秒)以等待更多数据进入并在此时间段后停止工作?(即,如果其余数据在3秒钟后到达,那么套接字将不再接收该数据吗?)

要么

  1. 接收到1024个字节的数据后,recv方法会立即停止工作吗?(是否会丢弃其他1000个字节?)

如果1.)是正确的……我有什么方法可以确定时间量,recv数据应该在返回之前等待,还是由系统确定?(即我可以告诉套接字在停止等待更多数据之前等待5秒吗?)

更新:假设,我有以下代码:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((sys.argv[1], port))
    s.send('Hello, world')
    data = s.recv(1024)
    print("received: {}".format(data))
    s.close()
Run Code Online (Sandbox Code Playgroud)

假设服务器发送的数据大小> 1024字节。我是否可以确定变量“ data”将包含所有数据(包括第1024个字节以外的数据)?如果不能确定该如何更改代码,以便始终可以确保变量“ data”将包含从服务器发送(一步或多步)的所有数据?

tde*_*ney 9

这取决于协议。某些协议(例如UDP)发送消息,并且每个协议仅返回1条消息recv。假设您正在专门讨论TCP,涉及多个因素。TCP是面向流的,并且由于诸如当前未完成的发送/接收数据量,线路上丢失/重新排序的数据包,延迟的数据确认以及Nagle算法(将一些小的发送延迟几百毫秒)之类的原因,随着客户端和服务器之间的对话的进行,行为可能会发生细微变化。

接收者只知道它正在获取字节流。它可以在任何recv上获得从1到完全请求的缓冲区大小的任何值。一侧的发送调用与另一侧的recv调用之间没有一对一的关联。

如果您需要确定消息边界,则取决于更高级别的协议来确定消息边界。以HTTP为例。它以\ r \ n分隔的头开始,然后具有客户端应期望接收的剩余字节数。客户端由于\ r \ n而知道如何读取标头,然后确切知道接下来要发送多少个字节。RESTful协议的魅力之一在于它们基于HTTP,并且已经有人发现了这些东西!

一些协议使用NUL来分隔消息。其他的则可能具有固定长度的二进制标头,其中包含即将到来的任何可变数据的计数。我喜欢zeromq,它在TCP之上具有可靠的消息传递系统。

有关接收发生的更多详细信息...

当您这样做时recv(1024),有6种可能性

  1. 没有接收数据。recv将等到有接收数据。您可以通过设置超时来更改它。

  2. 部分接收数据。您将立即获得该部分。其余的要么被缓冲,要么尚未发送,您只需要执行另一个recv即可获取更多内容(并且适用相同的规则)。

  3. 有超过1024个字节可用。您将获得1024个数据,其余数据将被缓冲在内核中,等待其他接收。

  4. 另一侧已关闭插座。您将获得0字节的数据。0表示您永远不会在该套接字上获得更多数据。但是,如果您继续要求数据,则将继续获得0个字节。

  5. 另一侧已重置套接字。你会得到一个例外。

  6. 发生了其他一些奇怪的事情,您将为此获得例外。

  • 也许值得知道的是,如果您使用 UDP(或 Unix 数据报)套接字,则任何比调用“recv()”时使用的缓冲区长的数据都将被丢弃。TCP(或流)套接字将如所描述的那样,为下一个“recv()”调用保留额外的内容。 (4认同)