python socket.recv() 方法如何知道已到达消息结尾?
How does the python socket.recv() method know that the end of the message has been reached?
假设我使用 1024 作为客户端套接字的缓冲区大小:
recv(1024)
假设服务器要发送给我的消息包含 2024 个字节。
我的套接字只能接收 1024 个字节。其他 1000 字节发生了什么?
- recv 方法是否会等待一定时间(比如 2 秒)以接收更多数据并在这段时间后停止工作? (即,如果其余数据在 3 秒后到达,则套接字将不再接收数据?)
或
- recv-method接收到1024字节的数据后会立即停止工作吗? (即会丢弃其他 1000 个字节吗?)
如果 1.) 是正确的...我有没有办法确定接收数据在返回之前应该等待的时间量,还是由系统确定? (即我可以告诉套接字在停止等待更多数据之前等待 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()
假设服务器发送大小> 1024 字节的数据。我可以确定变量 "data" 将包含所有数据(包括第 1024 个字节以外的数据)吗?
如果我不能确定这一点,我将如何更改代码以便我始终可以确保变量 "data" 将包含从服务器(通过一个或多个步骤)发送的所有数据?
这取决于协议。某些协议(如 UDP)发送消息并且每个 recv
恰好返回 1 条消息。假设您专门谈论 TCP,则涉及多个因素。 TCP 是面向流的,并且由于诸如当前未完成的 send/recv 数据量、在线路上的 lost/reordered 数据包、延迟的数据确认以及 Nagle 算法(将一些小的发送延迟几百毫秒),它的行为可以随着客户端和服务器之间对话的进行而微妙地改变。
接收方只知道它正在获取字节流。它可以在任何 recv 上获取从 1 到完全请求的缓冲区大小的任何内容。一侧的发送调用与另一侧的接收调用之间没有 one-to-one 相关性。
如果您需要确定消息边界,则由更高级别的协议来确定。以 HTTP 为例。它以 \r\n 分隔的 header 开头,然后计算客户端应该接收的剩余字节数。客户端知道如何读取 header 因为 \r\n 然后确切地知道接下来有多少字节。 RESTful 协议的部分魅力在于它们是基于 HTTP 的,而且其他人已经解决了这个问题!
一些协议使用 NUL 来分隔消息。其他人可能有一个固定长度的二进制 header,其中包括对即将到来的任何可变数据的计数。我喜欢 zeromq,它在 TCP 之上有一个强大的消息传递系统。
有关接收发生的情况的更多详细信息...
当你recv(1024)
时,有6种可能
没有接收数据。 recv
会等到有接收数据。您可以通过设置超时来更改它。
有部分接收数据。你会马上得到那部分。其余部分要么已缓冲,要么尚未发送,您只需再执行一次接收即可获得更多(并且适用相同的规则)。
可用字节数超过 1024。您将获得 1024 个数据,其余数据缓冲在内核中等待另一个接收。
对方关闭了socket。您将获得 0 字节的数据。 0 意味着您永远不会在该套接字上获得更多数据。但是如果你一直要求数据,你会一直得到 0 字节。
对方重置了socket。你会得到一个例外。
其他一些奇怪的事情发生了,你会得到一个例外。
假设我使用 1024 作为客户端套接字的缓冲区大小:
recv(1024)
假设服务器要发送给我的消息包含 2024 个字节。 我的套接字只能接收 1024 个字节。其他 1000 字节发生了什么?
- recv 方法是否会等待一定时间(比如 2 秒)以接收更多数据并在这段时间后停止工作? (即,如果其余数据在 3 秒后到达,则套接字将不再接收数据?)
或
- recv-method接收到1024字节的数据后会立即停止工作吗? (即会丢弃其他 1000 个字节吗?)
如果 1.) 是正确的...我有没有办法确定接收数据在返回之前应该等待的时间量,还是由系统确定? (即我可以告诉套接字在停止等待更多数据之前等待 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()
假设服务器发送大小> 1024 字节的数据。我可以确定变量 "data" 将包含所有数据(包括第 1024 个字节以外的数据)吗? 如果我不能确定这一点,我将如何更改代码以便我始终可以确保变量 "data" 将包含从服务器(通过一个或多个步骤)发送的所有数据?
这取决于协议。某些协议(如 UDP)发送消息并且每个 recv
恰好返回 1 条消息。假设您专门谈论 TCP,则涉及多个因素。 TCP 是面向流的,并且由于诸如当前未完成的 send/recv 数据量、在线路上的 lost/reordered 数据包、延迟的数据确认以及 Nagle 算法(将一些小的发送延迟几百毫秒),它的行为可以随着客户端和服务器之间对话的进行而微妙地改变。
接收方只知道它正在获取字节流。它可以在任何 recv 上获取从 1 到完全请求的缓冲区大小的任何内容。一侧的发送调用与另一侧的接收调用之间没有 one-to-one 相关性。
如果您需要确定消息边界,则由更高级别的协议来确定。以 HTTP 为例。它以 \r\n 分隔的 header 开头,然后计算客户端应该接收的剩余字节数。客户端知道如何读取 header 因为 \r\n 然后确切地知道接下来有多少字节。 RESTful 协议的部分魅力在于它们是基于 HTTP 的,而且其他人已经解决了这个问题!
一些协议使用 NUL 来分隔消息。其他人可能有一个固定长度的二进制 header,其中包括对即将到来的任何可变数据的计数。我喜欢 zeromq,它在 TCP 之上有一个强大的消息传递系统。
有关接收发生的情况的更多详细信息...
当你recv(1024)
时,有6种可能
没有接收数据。
recv
会等到有接收数据。您可以通过设置超时来更改它。有部分接收数据。你会马上得到那部分。其余部分要么已缓冲,要么尚未发送,您只需再执行一次接收即可获得更多(并且适用相同的规则)。
可用字节数超过 1024。您将获得 1024 个数据,其余数据缓冲在内核中等待另一个接收。
对方关闭了socket。您将获得 0 字节的数据。 0 意味着您永远不会在该套接字上获得更多数据。但是如果你一直要求数据,你会一直得到 0 字节。
对方重置了socket。你会得到一个例外。
其他一些奇怪的事情发生了,你会得到一个例外。