使用python解码tcp数据包

发布于 2024-08-19 15:28:47 字数 1077 浏览 2 评论 0原文

我正在尝试解码通过 TCP 连接收到的数据。数据包很小,不超过100字节。然而,当它们很多时,我会收到一些连接在一起的数据包。有没有办法防止这种情况。我正在使用 python,

我尝试分离数据包,我的源代码如下。数据包以STX字节开始,以ETX字节结束,STX后面的字节是数据包长度,(数据包长度小于5无效)校验和是ETX之前的最后一个字节

def decode(data):
  while True:
    start = data.find(STX)
    if start == -1: #no stx in message
        pkt = ''
        data = ''
        break
    #stx found , next byte is the length
    pktlen = ord(data[1])
    #check message ends in ETX (pktken -1) or checksum invalid
    if pktlen < 5 or data[pktlen-1] != ETX or checksum_valid(data[start:pktlen]) == False:
        print "Invalid Pkt"
        data = data[start+1:]
        continue
    else:
        pkt = data[start:pktlen]
        data = data[pktlen:]
        break

return data , pkt

我这样使用它

#process reports
try:
    data = sock.recv(256) 
except: continue 
else:
    while data:
        data, pkt = decode(data) 
        if pkt:
           process(pkt)

此外,如果有多个数据流中的数据包,最好将数据包作为列表的集合返回还是只返回第一个数据包

我对python不太熟悉,只会C,这种方法可以吗?任何建议将不胜感激。提前致谢

谢谢

I am trying to decode data received over a tcp connection. The packets are small, no more than 100 bytes. However when there is a lot of them I receive some of the the packets joined together. Is there a way to prevent this. I am using python

I have tried to separate the packets, my source is below. The packets start with STX byte and end with ETX bytes, the byte following the STX is the packet length, (packet lengths less than 5 are invalid) the checksum is the last bytes before the ETX

def decode(data):
  while True:
    start = data.find(STX)
    if start == -1: #no stx in message
        pkt = ''
        data = ''
        break
    #stx found , next byte is the length
    pktlen = ord(data[1])
    #check message ends in ETX (pktken -1) or checksum invalid
    if pktlen < 5 or data[pktlen-1] != ETX or checksum_valid(data[start:pktlen]) == False:
        print "Invalid Pkt"
        data = data[start+1:]
        continue
    else:
        pkt = data[start:pktlen]
        data = data[pktlen:]
        break

return data , pkt

I use it like this

#process reports
try:
    data = sock.recv(256) 
except: continue 
else:
    while data:
        data, pkt = decode(data) 
        if pkt:
           process(pkt)

Also if there are multiple packets in the data stream, is it best to return the packets as a collection of lists or just return the first packet

I am not that familiar with python, only C, is this method OK. Any advice would be most appreciated. Thanks in advance

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

生生不灭 2024-08-26 15:28:47

我将创建一个类,负责解码流中的数据包,如下所示:

class PacketDecoder(object):

    STX = ...
    ETX = ...

    def __init__(self):
        self._stream = ''

    def feed(self, buffer):
        self._stream += buffer

    def decode(self):
        '''
        Yields packets from the current stream.
        '''
        while len(self._stream) > 2:
            end = self._stream.find(self.ETX)
            if end == -1:
                break

            packet_len = ord(self._stream[1])
            packet = self._stream[:end]
            if packet_len >= 5 and check_sum_valid(packet):
                yield packet
            self._stream = self._stream[end+1:]

然后像这样使用:

decoder = PacketDecoder()
while True:
    data = sock.recv(256) 
    if not data:
        # handle lost connection... 
    decoder.feed(data)
    for packet in decoder.decode():
        process(packet)

I would create a class that is responsible for decoding the packets from a stream, like this:

class PacketDecoder(object):

    STX = ...
    ETX = ...

    def __init__(self):
        self._stream = ''

    def feed(self, buffer):
        self._stream += buffer

    def decode(self):
        '''
        Yields packets from the current stream.
        '''
        while len(self._stream) > 2:
            end = self._stream.find(self.ETX)
            if end == -1:
                break

            packet_len = ord(self._stream[1])
            packet = self._stream[:end]
            if packet_len >= 5 and check_sum_valid(packet):
                yield packet
            self._stream = self._stream[end+1:]

And then use like this:

decoder = PacketDecoder()
while True:
    data = sock.recv(256) 
    if not data:
        # handle lost connection... 
    decoder.feed(data)
    for packet in decoder.decode():
        process(packet)
淡莣 2024-08-26 15:28:47

TCP 在接口级别提供数据流,而不是单个数据包。如果您想要离散数据包,您可以使用 UDP(并自行处理丢失或无序的数据包),或内联一些数据分隔符。听起来您已经在这样做了,并使用 STX/ETX 作为分隔符。然而,正如您所注意到的,您从 TCP 堆栈的一个数据块中获取多条消息。

请注意,除非您正在进行其他处理,否则您显示的代码中的 data 不一定包含整数数量的消息。也就是说,最后一个STX很可能不会有匹配的ETX。 ETX 将位于下一个没有 STX 的data 块中。

您可能应该从 TCP 数据流中读取各个消息并在发生时返回它们。

TCP provides a data stream, not individual packets, at the interface level. If you want discrete packets, you can use UDP (and handle lost or out of order packets on your own), or put some data separator inline. It sounds like you are doing that already, with STX/ETX as your separators. However, as you note, you get multiple messages in one data chunk from your TCP stack.

Note that unless you are doing some other processing, data in the code you show does not necessarily contain an integral number of messages. That is, it is likely that the last STX will not have a matching ETX. The ETX will be in the next data chunk without an STX.

You should probably read individual messages from the TCP data stream and return them as they occur.

迎风吟唱 2024-08-26 15:28:47

尝试 scapy,一个强大的交互式数据包操作程序。

Try scapy, a powerful interactive packet manipulation program.

羞稚 2024-08-26 15:28:47

数据从哪里来?与其尝试手动解码,为什么不使用优秀的 Impacket 包:

http://oss .coresecurity.com/projects/impacket.html

Where does the data come from ? Instead of trying to decode it by hand, why not use the excellent Impacket package:

http://oss.coresecurity.com/projects/impacket.html

拥抱影子 2024-08-26 15:28:47

漂亮又简单...:)
诀窍在于 file 对象。

f=sock.makefile()
while True:
  STX = f.read(1)
  pktlen = f.read(1)
  wholePacket = STX + pktlen + f.read(ord(pktlen)-2)
  doSomethingWithPacket(wholePacket)

就是这样!(使用 TCP 时也不需要检查校验和。)

这是一个更“健壮”(?)的版本(它使用 STX 和校验和):

f=sock.makefile()
while True:
  while f.read(1)!=STX:
    continue
  pktlen = f.read(1)
  wholePacket = STX + pktlen + f.read(ord(pktlen)-2)
  if checksum_valid(wholePacket):
    doSomethingWithPacket(wholePacket)

Nice and simple... :)
The trick is in the file object.

f=sock.makefile()
while True:
  STX = f.read(1)
  pktlen = f.read(1)
  wholePacket = STX + pktlen + f.read(ord(pktlen)-2)
  doSomethingWithPacket(wholePacket)

And that's it! (There is also no need to check checksums when using TCP.)

And here is a more "robust"(?) version (it uses STX and checksum):

f=sock.makefile()
while True:
  while f.read(1)!=STX:
    continue
  pktlen = f.read(1)
  wholePacket = STX + pktlen + f.read(ord(pktlen)-2)
  if checksum_valid(wholePacket):
    doSomethingWithPacket(wholePacket)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文