2017-05-10 1 views
0

파이썬 응용 프로그램에서 "writeDelmitedTo()"라는 자바 응용 프로그램에서 보낸 protobuf 메시지를 수신하려고합니다.구분 된 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는 스트림 프로토콜이며, 한쪽이 다른 쪽 끝에서 하나의 send와 결합 된 recv에 말한다 아무것도 없다. 메시지 기반 프로토콜은 수신자가 메시지 경계를 찾는 방법을 알 수 있도록 경계를 표시하는 방법이 필요합니다.

writeDelimitedTo docsvarint 크기가 전송 된 다음 데이터가 전송된다고 말합니다. 따라서 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

관련 문제