【问题标题】:socket.recv() receives less bytes than expectedsocket.recv() 接收的字节数少于预期
【发布时间】:2019-11-24 11:17:32
【问题描述】:

这段代码下载了大部分文件,但不是所有文件(在一个while循环内)知道我做错了什么吗?

data = csocket.recv(1024)
with open(filename, 'wb') as file_to_save:
    while data:
      file_to_save.write(data)
      time.sleep(.008)
      data = csocket.recv(1024)
      if len(data) < 1024:
         break

下载 38,616 字节大小的文件时,此代码下载大约 600 字节。

【问题讨论】:

  • 明显的答案,看起来像 len(data)
  • 抱歉错过了'data'的声明,现在编辑一下代码。
  • 到底遗漏了多少...?
  • 如果我下载一个大小为 38,616 字节的文件,它大约短 600 字节。 (38,008 字节)

标签: python python-3.x sockets file-sharing


【解决方案1】:

通常,recv() 函数不保证返回您“请求”的字节总数。该参数只是您希望接收的最大字节数,但如果缓冲区中可用,该函数可以返回比这更少的字节数。这是来自https://docs.python.org/3/howto/sockets.html

的实现
    def myreceive(self):
        chunks = []
        bytes_recd = 0
        while bytes_recd < MSGLEN:
            chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
            if chunk == b'':
                raise RuntimeError("socket connection broken")
            chunks.append(chunk)
            bytes_recd = bytes_recd + len(chunk)
        return b''.join(chunks)

如您所见,该函数重复 recv() 直到达到预期的字节数。每个块到达后,新的 recv() 请求最大字节数MSGLEN – bytes_recd。 min() 用于将每个块的接收字节数限制为 2048。当 recv() 函数返回 0 字节(chunk == b'')时,表示对方关闭了连接。

对于您的情况,len(data) 有时会返回小于 1024。您的中断条件应为 if len(data) &lt; 1:

【讨论】:

  • 当使用 if len(data)
  • 如果对方没有关闭连接,您将永远不会收到零字节,您的代码将在 recv(1024) 中永远等待。您需要为循环找到其他中断条件。这在流连接中很常见,您可以使用特殊字符来标记传输的结束(它不应该出现在消息正文中),您也可以在收到 X 个字节后完成(首先发送包长度)或实现你自己的协议。您的问题的标题具有误导性,也许您可​​以使用类似“socket.recv() 接收的字节数少于预期”
  • 你能举个例子吗?
  • 我实现了您的建议“您可以使用特殊字符来标记传输结束”并且文件接收到的字节数比预期的多,这是否意味着文件已损坏?
  • 不一定。这可能是编码问题,或者您发送的内容比您想象的要多(例如您开始发送第二个文件),或者您没有正确计算预期字符的数量。如果您的传输结束标记超过一个字节,请检查字节顺序(小端或大端)。由于您的原始问题已得到回答,请将 ti 标记为已回答。如果您还有其他问题,请提出新问题。
猜你喜欢
  • 1970-01-01
  • 2012-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-04
  • 1970-01-01
  • 1970-01-01
  • 2018-03-02
相关资源
最近更新 更多