【问题标题】:Python socket recv functionPython 套接字接收函数
【发布时间】:2020-10-06 09:40:20
【问题描述】:

在 python 套接字模块 recv 方法 socket.recv(bufsize[, flags]) docs here 中,它声明:

Receive data from the socket. The return value is a bytes object representing the data received.
The maximum amount of data to be received at once is specified by bufsize.

我知道bufsize代表一次接收到的最大数据量,如果接收到的数据量小于bufsize,说明另一端socket发送的字节数少比bufsize

第一次调用socket.recv(bufsize)返回的数据是否有可能是bufsize,但网络缓冲区中仍有数据?

例如。

data = socket.recv(10)
print(len(data))       # outputs 5
data = socket.recv(10) # calling `socket.recv(10)` returns more data without the
                       # socket on the other side doing `socket.send(data)`

示例中的场景是否会发生?这是否适用于 unix 域套接字以及常规 TCP/IP 套接字?

【问题讨论】:

  • 不知道 unix 套接字,但对于 TCP 套接字,答案是肯定的——您必须假设您收到的内容可能多于或少于任何一次 send() 调用的内容。这就是为什么您经常需要在 TCP 之上添加协议来获取分隔消息的原因。或者使用像 Websocket 这样的协议,它在 tcp 之上运行并确保消息完整性。

标签: python sockets networking


【解决方案1】:

网络通信的真正问题是接收方无法控制网络何时以及如何传递数据。

如果recv返回的数据大小小于请求的大小,这意味着recv调用的那一刻,本地网络中没有更多数据可用缓冲。所以如果你能确定:

  • 发件人已停止发送数据
  • 网络可以传送所有数据

然后一个新的revc 调用将被阻塞。

问题在于,在现实世界的情况下,您永远无法确定上述两个假设。 TCP 是一种流协议,它只保证所有发送的字节都会以正确的顺序到达接收方。但是如果不提供时间保证,发送的数据包可以被网络分片或重新组装(从发送方的网络 TCP 堆栈开始,到接收方的 TCP 堆栈结束)

【讨论】:

  • 所以在 recv 调用时网络缓冲区是空的。对于 TCP 套接字,没有时间保证,那么 unix 域套接字呢?仅考虑 1 个send() 调用和 1 个recv() 调用,是否会出现上述情况?
  • @ShideFoo 同样。 send()recv() 的规范中没有任何内容可以让您做出这样的假设。
【解决方案2】:

找到了一个类似的帖子跟进:How can I reliably read exactly n bytes from a TCP socket?

基本上使用socket.makefile() 来返回一个文件对象并调用read(num_bytes) 来准确返回请求的数量,否则阻塞。

fh = socket.makefile(mode='b')
data = fh.read(LENGTH_BYTES)

【讨论】:

    猜你喜欢
    • 2020-09-24
    • 1970-01-01
    • 1970-01-01
    • 2016-01-27
    • 1970-01-01
    • 2018-05-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多