如何使用Python解析由自定义协议包组成的TCP流

0 人关注

假设我们定义了一个用户级的TCP数据包解析协议,如下所示。

  A User-Level TCP Packet:
  ---------- ------ ---------- ----------------------------
 | F1F2F3F4 | Type |  Length  |         Packet Body        |
  ---------- ------ ---------- ----------------------------
 1. F1F2F3F4: beginning of a packet, hex data (4 bytes)
 2. Type:     denotes what type of this packet (2 bytes)
 3. Length:   how many bytes the packet contains except F1F2F3F4
              Packets may have different length (2 bytes)
 4. PacketBody: Real data a packet contains

假设我们有一对TCP通信,它们通过发送这种格式的数据包来相互交换数据。通信者发送一时之间,大量的数据包通过一个套接字,有时他们甚至以这种方式发送文件。

在C/C++语言中,我将分配一个足够大的缓冲区来存储从套接字中读取的数据,然后扫描F1F2F3F4缓冲区内的,并找到Length字段。 如果该数据小于Length,然后等待更多。

现在我需要在Python中实现这一点,有人知道怎么做吗?

2 个评论
在Python中,原则上是一样的,从socket中读取,扫描F1F2F3F4,得到长度,如果数据小于长度,则等待更多。你真的需要寻找开头吗?有多少位的类型和长度?
类型和长度都是两个字节。
python
linux
sockets
networking
tcp
Wallace
Wallace
发布于 2014-11-15
2 个回答
Daniel
Daniel
发布于 2014-11-15
0 人赞同

would look like this:

import struct
def recv_full(sock, cnt):
    buf = []
    while cnt>0:
        data = sock.recv(min(10240, cnt))
        buf.append(data)
        cnt -= len(data)
    return ''.join(buf)
def recv_packet(sock):
    header, type, length = struct.unpack('>IHH', recv_full(sock, 8))
    assert header == 0xf1f2f3f4
    return type, recv_full(length - 4)
    
问题是流中可能混有脏数据,更糟糕的是,数据包可能被破坏,变得不完整。因此,我们不应该认为TCP数据流是由一个一个的正常数据包组成的。
你想如何修复一个被破坏的数据包?那么你必须假设 f1f2f3f4 从未在数据包主体中使用。
处理这种情况的方法之一是放弃该数据包。例如,如果一个数据包的长度字段为500字节,但真正的数据只有100字节长(这意味着数据超过500字节,但在第501字节处没有找到F1F2F4),那么我们就必须放弃这个数据包。
user590028
user590028
发布于 2014-11-15
0 人赞同

I would suggest something like this

import struct
hdr = sock.recv(8, socket.MSG_WAITALL)
(beg, typ, pktlen) = struct.unpack('!IHH', hdr)