从TCP流中解析数据包

时间:2014-02-21 22:40:19

标签: 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", msg)
        if len(msg) >= msg_len:
            protocol.parse_packet(msg[:msg_len])
            msg = msg[msg_len:]
            msg_len = 0

这很有效,并且很好地服务了我很多次,但我总是对msg += sock.recv(4096)中附加的字符串感到厌烦。对于小数据包,这不是太糟糕,因为为这些小字符串分配新存储的开销并不坏。但对于大型数据包(MB),Python的字符串实现中会在幕后进行大量复制。

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

1 个答案:

答案 0 :(得分:1)

首先快速建议:为了清楚起见,您可能希望将packet_size重命名为msg_len。您尝试从TCP流解析的是应用程序级协议消息,而不是TCP段(也称为TCP数据包)。

但要解决您的问题:更有效的方法是,当您收到邮件标头时,分配长度为bytearray的第二个固定大小的msg_len缓冲区。用它来存储您随后读入的数据。