TCP套接字读取不完整

时间:2017-10-23 17:02:35

标签: python sockets tcp server

我正在使用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一起发送,但是当收到邮件时,当我打印到达邮件的长度时,长度有时是错误的,有时是正确的。< / p>

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

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

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

编辑1:我稍微检查过这个question,它提到客户端中的所有发送命令都可能无法通过服务器中的单个recv接收,但我无法理解将其应用于练习。

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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仅返回请求的字节数,并在缓冲区中留下任何额外的内容。