Python TCP Socket在recv中丢失数据

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (247)

我写了一个简单的套接字客户端,用于在Python 3.4中读取数据

我遇到的问题是,当服务器发送少量数据(大约1000)字节时,它会完美地读取它,但是当处理大量数据(9500字节)时,它只会给我一小部分数据数据(如1100-ish块)。我似乎无法弄清楚为什么它在处理大量数据时表现得如此不规律。我知道我的数据不大于ssize_t最大值32767

它在处理小数据时完美地工作,并且在处理大量数据时完全变为180并且表现不同。我知道这不是TCP服务器中的问题,因为我使用PHP TCP客户端测试它,并且在处理大量数据时它工作得很好。

任何帮助是极大的赞赏。

import socket
import json

# Written in Python 3.4.

class SocketClient:

    def __init__(self, host, port, format, timeout = None):
        # Constructor
        self.host = host
        self.port = port
        self.format = format
        self.timeout = timeout

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def send(self, firstname, lastname, parameters = [], format = 'json'):
        if self.socket is not None:
            self.socket.connect((self.host, self.port))

            data = {}
            data['firstname'] = firstname
            data['lastname'] = lastname
            data['parameters'] = parameters
            data['format'] = format

            self.socket.send(bytes(json.dumps(data), "utf-8"))

            result = self.socket.recv(32767)
            result = result.decode()

            return result

    def shutdown(self):
        if socket is not None:
            self.socket.shutdown(socket.SHUT_RDWR)
            self.socket.close()


if __name__ == __main__:
    client = SocketClient("127.0.0.1", 8080, 'json')
    response = client.send('foo', 'bar', ['foobar'])
    print(response)
    client.shutdown()
提问于
用户回答回答于

TCP是一种流媒体协议。数据以字节为单位传递,其中长度由许多因素决定。一个是,内部缓冲区限制在几千字节。你永远不能一次读取32767个字节。唯一的保证recv是,你得到至少1个字节,最多你说的字节数。您的代码必须处理这个问题,这意味着,recv在您拥有所需的字节数之前,您必须执行多个调用。这意味着另一方面,没有消息结束指示符或编码长度的协议严重受损。在您的情况下:您必须解析json字节流,直到发送有效的json表达式。但那怎么样1245.6?收到后是否完成112?要修复协议,只需使用json数据发送一些长度信息。

对于发送你应该使用sendall而不是send

用户回答回答于

你可以使用recv_into(buffer[, nbytes[, flags]])方法:

def readReliably(s,n):
    buf = bytearray(n)
    view = memoryview(buf)
    sz = s.recv_into(view,n)
    return sz,buf

def writeReliably(s,buf,n):
  sz = 0
  while sz < n:
    sz += s.send(buf[sz:],n-sz)

请参阅以下完整示例:https//stackoverflow.com/a/55446223/966789

while True:
  sk,skfrom = s.accept()
  sz,buf = io.readReliably(sk,4)
  a = struct.unpack("4B",buf)
  print repr(a)
  # ...
  io.writeReliably(sk,struct.pack("4B",*[0x01,0x02,0x03,0x04]))

扫码关注云+社区

领取腾讯云代金券