2017-05-10 21 views
0

私のpythonアプリケーション内に "writeDelmitedTo()"というJavaアプリケーションから送信されたprotobufメッセージを受け取ろうとしています。Pythonで区切られたProtobufメッセージをTCP経由で受信

いくつかの調査の後、私はすでにこのコードを読んで、ソケットからメッセージを読み取り、デコードして解析しました。

data = sock.recv() 
(size, position) = decoder._DecodeVarint(data, 0) 
msg = MessageWrapper_pb2.WrapperMessage().ParseFromString(data[position:position + size]) 

google.protobuf.message.DecodeErrorは次のとおりです。切り詰められたメッセージの例外。

同様の問題が発生した場合や、区切り文字のデータをソケットから読み取って正しく解析する方法を知っている人はいますか?

は編集:

これは私のために働いたソリューションです。

def read_java_varint_delimited_stream(sock): 
    buf = [] 
    data = sock.recv() 
    rCount = len(data) 
    (size, position) = decoder._DecodeVarint(data, 0) 

    buf.append(data) 
    while rCount < size+1: 
     data = sock.recv(size+1-rCount) 
     rCount += len(data) 
     buf.append(data) 

    return b''.join(buf), size, position 

def readMessage(sock): 
    data, size, position = read_java_varint_delimited_stream(sock) 
    msg = MessageWrapper_pb2.WrapperMessage() 
    msg.ParseFromString(data[position:position + size]) 

    return msg 

答えて

0

TCPは、ストリームプロトコルであり、一端にrecvは、もう一方の端に単一sendとペアになっていると言うものは何もありません。メッセージベースのプロトコルは、受信者がメッセージの境界を見つける方法を知るように、境界をマークする何らかの方法を必要とします。

writeDelimitedTo docsは、varintサイズが送信され、次にデータが送信されるとします。だから、varintを読んで、そのバイト数を読んでください。

さらに深く掘り下げると、varint docsは、バイトの上位ビットを使用して継続をマークすることによってその値がどのようにエンコードされるかを記述します。私たちは独自のデコーダを書くことができます

import struct 

def read_java_varint_delimited_stream(sock): 
    sz = 0 
    while True: 
     vbyte, = struct.unpack('b', sock.recv(1)) 
     sz = (vbyte << 7) + (vbyte & 0x7f) 
     if not vbyte & 0x80: 
      break 
    data = [] 
    while sz: 
     buf = sock.recv(sz) 
     if not buf: 
      raise ValueError("Buffer receive truncated") 
     data.append(buf) 
     sz -= len(buf) 
    return b''.join(buf) 
+0

計算されたサイズには何か問題がありましたが、ループが決して終わらないように常に大きかったです。私は関数を少し変更しました(上記参照)。 – ElSchuer

関連する問題