python socket.recv() 方法如何知道已经到达消息末尾? [英] How does the python socket.recv() method know that the end of the message has been reached?

查看:241
本文介绍了python socket.recv() 方法如何知道已经到达消息末尾?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Let's say I'm using 1024 as buffer size for my client socket:

recv(1024)

让我们假设服务器要发送给我的消息包含 2024 个字节.我的套接字只能接收 1024 个字节.其他 1000 个字节发生了什么?

Let's assume the message the server wants to send to me consists of 2024 bytes. Only 1024 bytes can be received by my socket. What's happening to the other 1000 bytes?

  1. recv 方法是否会等待一段时间(比如 2 秒)以获取更多数据并在此时间跨度后停止工作?(即,如果剩余的数据在 3 秒后到达,套接字将不再接收数据?)

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

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

In case that 1.) is correct ... is there a way for me to to determine the amount of time, the recv data should wait before returning or is it determined by the system? (I.e. could I tell the socket to wait for 5 seconds before stopping to wait for more data?)

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

UPDATE: Assume, I have the following code:

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()

假设服务器发送的数据大小 > 1024 字节.我可以确定变量数据"将包含所有数据(包括第 1024 个字节之后的数据)吗?如果我不能确定这一点,我将如何更改代码,以便我始终可以确定变量数据"将包含从服务器发送的所有数据(在一个或多个步骤中)?

Assume that the server sends data of size > 1024 bytes. Can I be sure that the variable "data" will contain all the data (including those beyond the 1024th byte)? If I can't be sure about that, how would I have to change the code so that I can always be sure that the variable "data" will contain all the data sent (in one or many steps) from the server?

推荐答案

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

It depends on the protocol. Some protocols like UDP send messages and exactly 1 message is returned per recv. Assuming you are talking about TCP specifically, there are several factors involved. TCP is stream oriented and because of things like the amount of currently outstanding send/recv data, lost/reordered packets on the wire, delayed acknowledgement of data, and the Nagle algorithm (which delays some small sends by a few hundred milliseconds), its behavior can change subtly as a conversation between client and server progresses.

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

All the receiver knows is that it is getting a stream of bytes. It could get anything from 1 to the fully requested buffer size on any recv. There is no one-to-one correlation between the send call on one side and the recv call on the other.

如果您需要弄清楚消息边界,则可以由更高级别的协议来解决.以 HTTP 为例.它以 分隔的标头开始,然后计算客户端应该期望接收的剩余字节数.由于 ,客户端知道如何读取标头,然后确切地知道接下来有多少字节.RESTful 协议的部分魅力在于它们是基于 HTTP 的,而且其他人已经发现了这一点!

If you need to figure out message boundaries its up to the higher level protocols to figure that out. Take HTTP for example. It starts with a delimited header and then has a count of the remaining bytes the client should expect to receive. The client knows how to read the header because of the then knows exactly how many bytes are coming next. Part of the charm of RESTful protocols is that they are HTTP based and somebody else already figured this stuff out!

某些协议使用 NUL 来分隔消息.其他人可能有一个固定长度的二进制头,其中包括任何可变数据的计数.我喜欢 zeromq,它在 TCP 之上有一个强大的消息传递系统.

Some protocols use NUL to delimit messages. Others may have a fixed length binary header that includes a count of any variable data to come. I like zeromq which has a robust messaging system on top of TCP.

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

More details on what happens with receive...

当你做recv(1024)时,有6种可能

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

  1. There is no receive data. recv will wait until there is receive data. You can change that by setting a timeout.

有部分接收数据.你马上就会得到那部分.其余的要么已缓冲,要么尚未发送,您只需再执行一次接收即可获得更多(适用相同的规则).

There is partial receive data. You'll get that part right away. The rest is either buffered or hasn't been sent yet and you just do another recv to get more (and the same rules apply).

可用的字节数超过 1024 个.您将获得 1024 个该数据,其余数据缓存在内核中,等待下一次接收.

There is more than 1024 bytes available. You'll get 1024 of that data and the rest is buffered in the kernel waiting for another receive.

对方已经关闭了socket.您将获得 0 字节的数据.0 意味着您永远不会在该套接字上获得更多数据.但是,如果您继续请求数据,您将继续获得 0 个字节.

The other side has shut down the socket. You'll get 0 bytes of data. 0 means you will never get more data on that socket. But if you keep asking for data, you'll keep getting 0 bytes.

对方重置了socket.你会得到一个例外.

The other side has reset the socket. You'll get an exception.

发生了其他一些奇怪的事情,你会得到一个例外.

Some other strange thing has gone on and you'll get an exception for that.

这篇关于python socket.recv() 方法如何知道已经到达消息末尾?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆