1

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だけがこの方法で問題ありません。任意のアドバイスをいただければ幸いです。前もって感謝します

ありがとう

4

5 に答える 5

5

次のように、ストリームからのパケットのデコードを担当するクラスを作成します。

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)
于 2010-02-02T15:51:33.517 に答える
4

TCPは、インターフェイスレベルで、個々のパケットではなく、データストリームを提供します。個別のパケットが必要な場合は、UDPを使用するか(失われたパケットや順序が正しくないパケットを自分で処理する)、データセパレータをインラインに配置することができます。STX / ETXをセパレーターとして使用して、すでにそれを行っているようです。ただし、お気づきのとおり、TCPスタックから1つのデータチャンクに複数のメッセージが含まれています。

他の処理を行っていない限り、data表示するコードには必ずしも整数個のメッセージが含まれているとは限らないことに注意してください。つまり、最後のSTXに一致するETXがない可能性があります。ETXはdata、STXなしで次のチャンクになります。

おそらく、TCPデータストリームから個々のメッセージを読み取り、発生したときにそれらを返す必要があります。

于 2010-02-02T13:33:40.307 に答える
3

強力なインタラクティブパケット操作プログラムであるscapyをお試しください。

于 2010-02-02T14:02:00.903 に答える
0

データはどこから来ていますか?手作業でデコードする代わりに、優れたImpacketパッケージを使用してみませんか。

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

于 2010-02-02T13:53:34.167 に答える
0

素晴らしくてシンプル... :) トリックはファイルオブジェクトにあります。

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)
于 2010-04-10T22:10:01.593 に答える