Python TCP套接字在recv中丢失数据[行为怪异]

2024-04-25 06:06:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我编写了一个简单的socket客户机来读取python3.4中的数据

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

它在处理小数据时工作得很好,而在处理大量数据时则完全不同。我知道这在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()

Tags: 数据selfnonesendjsonformathostdata
3条回答

TCP是一种流协议。数据以字节为单位传递,长度由许多因素决定。一个是,内部缓冲区被限制在大约1000个字节。你永远不能一次读取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 = 0
    while sz < n:
        k = s.recv_into(view[sz:],n-sz)
        sz += k
    # print 'readReliably()',sz
    return sz,buf

def writeReliably(s,buf,n):
    sz = 0
    while sz < n:
        k = s.send(buf[sz:],n-sz)
        sz += k
    # obj = s.makefile(mode='w')
    # obj.flush()
    # print 'writeReliably()',sz
    return sz

完整示例请参见:https://stackoverflow.com/a/55446223/966789

^{pr2}$

这就是recv在不止一种语言中的工作方式。。。https://docs.python.org/3.4/library/socket.html#socket.socket.recv

相关问题 更多 >