假设我使用1024作为客户端套接字的缓冲区大小:
recv(1024)
假设服务器想要发送给我的消息包含2024个字节。 我的套接字只能接收1024个字节。其他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()
假设服务器发送大小为>的数据。 1024字节。我可以确定变量“data”将包含所有数据(包括第1024字节以外的数据)吗? 如果我不能确定这一点,我将如何更改代码以便始终确保变量“data”将包含从服务器发送的所有数据(在一个或多个步骤中)?
答案 0 :(得分:8)
这取决于协议。 UDP等一些协议发送消息,每recv
返回一条消息。假设您具体谈论TCP,则涉及多个因素。 TCP是面向流的,因为诸如当前未完成的发送/ recv数据量,线路上丢失/重新排序的数据包,数据的延迟确认以及Nagle算法(将一些小发送延迟几百毫秒),当客户端和服务器之间的对话进展时,行为会发生微妙的变化。
所有接收者都知道它正在获得一个字节流。它可以在任何recv上获得从1到完全请求的缓冲区大小的任何内容。一方的发送呼叫与另一方的recv呼叫之间没有一对一的关联。
如果您需要确定消息边界,那么可以找出更高级别的协议来解决这个问题。以HTTP为例。它以\ r \ n分隔的标头开头,然后计算客户端应该接收的剩余字节数。客户端知道如何读取标头,因为\ r \ n然后确切知道接下来会有多少字节。 RESTful协议的一部分魅力在于它们是基于HTTP的,其他人已经把这些东西想出来了!
某些协议使用NUL来分隔消息。其他人可能有一个固定长度的二进制标题,其中包含任何可变数据的计数。我喜欢zeromq,它在TCP之上有一个强大的消息传递系统。
有关收到会发生什么的详细信息...
执行recv(1024)
时,有6种可能性
没有接收数据。 recv
将等待,直到收到数据。您可以通过设置超时来更改它。
有部分接收数据。你马上得到那个部分。其余的是缓冲或尚未发送,你只需再做一次recv以获得更多(并适用相同的规则)。
可用的字节数超过1024个。您将获得1024个该数据,其余数据将在内核中缓冲,等待另一次接收。
另一方已关闭套接字。您将获得0字节的数据。 0表示您永远不会在该套接字上获得更多数据。但是如果你不断要求数据,你将不断获得0字节。
另一方已重置套接字。你会得到一个例外。
其他一些奇怪的事情已经发生了,你会得到一个例外。