使用recv()方法时,有时我们无法接收到我们想要的那么多数据,就像使用send()一样。但是我们可以使用sendall()来解决发送数据的问题,那么接收数据呢?为什么没有这样的recvall()方法?
send
具有 recv
没有的额外信息:要发送多少数据。如果您有 100 字节的数据要发送,sendall
可以客观地判断第一次调用 send
发送的数据是否少于 100 字节,并不断发送数据,直到发送完所有 100 字节。
当您尝试读取 1024 字节,但只返回 512 字节时,您无法知道这是因为其他 512 字节被延迟而您应该尝试读取更多字节,还是只有 512 字节需要读取首先。你永远不能说会有更多的数据需要读取,从而使recvall
变得毫无意义。你最多能做的就是决定你愿意等待多长时间(超时)以及在放弃之前你愿意重试多少次。
您可能想知道为什么从文件读取和从套接字读取之间存在明显差异。对于文件,您可以从文件系统获得有关文件中有多少数据的额外信息,因此您可以可靠地区分 EOF 和其他可能阻止您读取可用数据的内容。套接字没有这样的元数据来源。
socket
类,以便每个
socket
对象将永远拥有 recvall 方法,直到你离开程序。import socket
# this functions blocks the socket until all the need data is given
def recvall(self, length):
received = 0
res = b''
while received < length:
res += self.recv(length - received)
received = len(res)
return res
socket.socket.recvall = recvall # socket class is patched
recvall
根本上令人困惑:你的假设是它会读取恰好 N 个字节,但根据名称,我认为它会完全耗尽流。
由于多种原因,完全耗尽流的操作是一个危险的 API,并且命名的模糊性使得它成为一个非常低效的 API。