【问题标题】:TCP socket reads out of turnTCP 套接字不按顺序读取
【发布时间】:2018-04-04 07:42:05
【问题描述】:

我正在使用 TCP 和 Python 套接字,将数据从一台计算机传输到另一台计算机。但是,recv 命令在服务器端读取的内容超出了应有的内容,我找不到问题。

client.py

while rval:
    image_string = frame.tostring()
    sock.sendall(image_string)
    rval, frame = vc.read()

server.py

while True:
    image_string = ""
    while len(image_string) < message_size:
        data = conn.recv(message_size)
        image_string += data

消息的长度是921600 (message_size),所以它与sendall一起发送,但是在收到时,当我打印到达消息的长度时,长度有时是错误的,有时是正确的。

921600
921600
921923 # wrong
922601 # wrong
921682 # wrong
921600
921600
921780 # wrong

如您所见,错误的到达没有模式。当我使用 TCP 时,我期望更多的一致性,但是似乎缓冲区混合在一起并且以某种方式接收下一条消息的一部分,因此产生了更长的消息。 这里有什么问题?

我尝试只添加代码的相关部分,如果您愿意,我可以添加更多,但是代码在localhost上运行良好,但在两台计算机上都失败了,所以除了传输部分应该没有错误。

Edit1:我检查了这个question,它提到客户端中的所有发送命令可能不会被服务器中的单个recv接收,但我不明白如何应用这个要练习。

【问题讨论】:

    标签: python sockets tcp server


    【解决方案1】:

    将 TCP 视为原始字节流。您有责任跟踪您在流中的位置并正确解释它。缓冲您阅读的内容,仅提取您当前需要的内容。

    这是一个(未经测试的)类来说明:

    class Buffer:
        def __init__(self,socket):
            self.socket = socket
            self.buffer = b''
        def recv_exactly(self,count):
            #  Could return less if socket closes early...
            while len(self.buffer) < count:
                data = self.socket.recv(4096)
                if not data: break
                self.buffer += data
            ret,self.buffer = self.buffer[:count],self.buffer[count:]
            return ret
    

    recv 始终请求相同数量的数据并将其排入缓冲区。 recv_exactly 只返回请求的字节数,并在缓冲区中留下任何额外的字节数。

    【讨论】:

      【解决方案2】:

      TCP 是一种流协议。您发送的数据块的大小与您接收的数据块的大小之间绝对没有联系。如果您想接收已知大小的数据,完全取决于您只请求那么多数据:您当前每次都请求数据的总长度,这将尝试读取太多,除非不太可能第一次.recv() 调用检索到整个数据的事件。基本上,您需要执行data = conn.recv(message_size - len(image_string)) 之类的操作来反映剩余数据量正在减少的事实。

      【讨论】:

      • 如果如你所说,我什至不需要,recv(message_size)就够了?
      • 无法保证单个 recv() 会读取所有请求的字节 - 如果到目前为止通过网络接收到的字节数会更少。
      • 如果它是基于流的,不应该在缓冲区填满消息之前读取吗?有没有资源可以让我阅读更多关于这个主题的信息,Python 文档在这种方式下不足。
      • @Rockybilly 想想看。消息到达您的套接字。你发出recv(X),你读到X字节。如果没有足够的字节到达您的套接字,则更少。到达套接字的字节数既不受服务器控制,也不受客户端控制。客户端只发送X 字节,TCP 保证最终所有这些字节都会以正确的顺序到达服务器。但不是什么时候。
      • @freakish 所以我应该在一个 for 循环中接收,在那里我接收固定大小,并在达到总数时退出。但是什么是好的缓冲区大小,就速度而言,最大大小是多少?是64K吗?假设我选择了 4096,我怎么能确定,在慢速连接中,所有 4096 字节都将在一次 recv 操作中收到?
      猜你喜欢
      • 1970-01-01
      • 2016-08-10
      • 2019-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-06
      相关资源
      最近更新 更多