从tcp套接字获取GPB数据并对其进行解码

时间:2018-04-04 03:15:42

标签: python protocol-buffers tornado

我有一个通过tcp传输gpb数据消息的应用程序。 tcp头是12个字节(msg_type,encode_type,msg_version,flags,msg_length)。然后我使用msg_length获取数据。

import json
import logging
from tornado.tcpserver import TCPServer
from tornado.iostream import StreamClosedError
from tornado import gen
from tornado.ioloop import IOLoop
from struct import Struct, unpack
from telemetry_pb2 import Telemetry

class TelemetryServer(TCPServer):
    def __init__(self):
        super().__init__()
        self.header_size = 12
        self.header_struct = Struct('>hhhhi')
        self._UNPACK_HEADER = self.header_struct.unpack

    @gen.coroutine
    def handle_stream(self, stream, address):
        print(f"Got connection from {address}")
        while not stream.closed():
            try:
                header_data = yield stream.read_bytes(self.header_size)
                msg_type, encode_type, msg_version, flags, msg_length = self._UNPACK_HEADER(header_data)
                encoding = {1:'gpb', 2:'json'}[encode_type]
                msg_data = b''
                print(encode_type)
                if encode_type == 1:
                    print(f'Got {msg_length} bytes from {address} with encoding {encoding}')
                    while len(msg_data) < msg_length:
                        packet = yield stream.read_bytes(msg_length - len(msg_data))
                        msg_data += packet
                    print(msg_data)
                    gpb_parser =Telemetry()
                    gpb_data = gpb_parser.ParseFromString(msg_data.decode('ascii'))
                    print(gpb_data.node_id)
                else:
                    print(f'Got {msg_length} bytes from {address} with encoding {encoding}')
                    while len(msg_data) < msg_length:
                        packet = yield stream.read_bytes(msg_length - len(msg_data))
                        msg_data += packet
                    json_data = json.loads(msg_data.decode("ascii"))
            except Exception as e:
                print(e)
                stream.close()



def main():
    server = TelemetryServer()
    server.bind(5556)
    server.start(0)
    IOLoop.current().start()

我得到的错误是数据是python bytes string

b'\n\x0fNCS5501-SE-LER1\x1a\t30seconds23Cisco-IOS-XR-ip-bfd-oper:bfd/ipv4-multi-hop-summary:\n2015-11-09@\xc8\x0cH\x92\x92\xa1\xf4\xa8,P\x92\x92\xa1\xf4\xa8,Zm\x08\x93\x92\xa1\xf4\xa8,z\x06\x12\x04keysz\\\x12\x07contentzQ\x12\rsession-statez\x0f\x12\x0btotal-count8\x00z\x0e\x12\ndown-count8\x00z\x0c\x12\x08up-count8\x00z\x11\x12\runknown-count8\x00h\x93\x92\xa1\xf4\xa8,'
'ascii' codec can't decode byte 0xc8 in position 94: ordinal not in range(128)

问题是如何将此字节字符串转换为字符串以便我可以解析它?

解决了它:

遥测对象不是解析器,它是完整的消息对象。所以可以做到

gpb_parser =Telemetry()
gpb_parser.ParseFromString(msg_data)
print(gpb_parser.node_id)

1 个答案:

答案 0 :(得分:0)

您使用ascii解码数据。但是数据的编码是不同的。使用数据的原始编码:

msg_data.decode(encode_type)
相关问题