Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从TCP流解析数据包_Python_Tcp_Stream_Packet - Fatal编程技术网

Python 从TCP流解析数据包

Python 从TCP流解析数据包,python,tcp,stream,packet,Python,Tcp,Stream,Packet,我经常编写简单的python TCP服务器,它们在解析长度前缀数据包后响应请求。假设已设置套接字,这通常看起来很像: def tcp_server_loop(): msg = '' msg_len = 0 while True: msg += sock.recv(4096) if len(msg) >= 4 and msg_len == 0: msg_len, = struct.unpack_from("!I"

我经常编写简单的python TCP服务器,它们在解析长度前缀数据包后响应请求。假设已设置套接字,这通常看起来很像:

def tcp_server_loop():
    msg = ''
    msg_len = 0
    while True:
        msg += sock.recv(4096)
        if len(msg) >= 4 and msg_len == 0:
            msg_len, = struct.unpack_from("!I", msg)
        if len(msg) >= msg_len:
            protocol.parse_packet(msg[:msg_len])
            msg = msg[msg_len:]
            msg_len = 0
这很管用,而且多次对我很有帮助,但我总是被
msg+=sock.recv(4096)
中附加的字符串所困扰。对于小数据包,这并不太糟糕,因为为这些小字符串分配新存储的开销也不错。但是对于大数据包(MBs),在Python的字符串实现中会在幕后进行大量复制


在C语言或类似语言中,环形缓冲区是一种明显的数据结构,其大小与您期望的最大数据包相当。但是,我还没有找到类似的Python实现。我想知道是否有人可以改进我上面的代码。如何实现这些类型的服务器?

首先是一个快速建议:为了清晰起见,您可能希望将
数据包大小
重命名为
msg\u len
。您试图从TCP流中解析出的是应用程序级协议消息,而不是TCP段(也称为TCP数据包)


但为了解决您的问题:更有效的方法是,当您收到消息头时,分配第二个固定大小的
bytearray
缓冲区,其长度
msg\u len
。使用此选项可存储随后读入的数据

针对变量名,更新了原始代码以使其更清晰。我不确定我是否理解创建bytearray如何提高效率。这不需要
msg
和字节数组之间的副本吗?当前的实现只将一个片段传递给协议解析器,我认为它不需要副本。是的,但我认为热点是在附加到
msg
时重新分配内存,而不是副本,只要您
sock.recv()
的字节数不大。如果您也将
msg
转换为
bytearray
,那么您可能会因为不需要解释器进行类型转换而获得一些额外的好处。