python 使用python解码tcp数据包

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2184181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 23:59:32  来源:igfitidea点击:

Decoding tcp packets using python

pythonstringtcpdecodingpackets

提问by mikip

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

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

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

我试图分开数据包,我的来源如下。包以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

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

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

Thanks

谢谢

回答by Bruno Oliveira

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)

回答by mpez0

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.

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

Note that unless you are doing some other processing, datain 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 datachunk without an STX.

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

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

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

回答by Oli

Try scapy, a powerful interactive packet manipulation program.

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

回答by fraca7

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

数据来自哪里?与其尝试手动解码,不如使用出色的 Impacket 包:

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

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

回答by Tarnay Kálmán

Nice and simple... :)The trick is in the fileobject.

很好很简单...... :)诀窍在于文件对象。

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.)

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

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

这是一个更“健壮”(?)的版本(它使用 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)