如何使用Python和Google的Protocol Buffers来反序列化通过TCP发送的数据

Jac*_*nds 17 python tcp protocol-buffers

我正在尝试编写一个应用程序,该应用程序使用Google的协议缓冲区通过TCP连接反序列化数据(使用协议缓冲区从另一个应用程序发送).问题是看起来Python中的协议缓冲区只能反序列化字符串中的数据.由于TCP没有明确定义的消息边界,并且我尝试接收的消息之一具有重复字段,因此在最终传递要反序列化的字符串之前,我不知道要尝试和接收多少数据.

在Python中执行此操作有什么好的做法吗?

J.J*_*.J. 36

不要只是将序列化数据写入套接字.首先发送一个包含序列化对象长度的固定大小的字段.

发送方大致是:

socket.write(struct.pack("H", len(data))    #send a two-byte size field
socket.write(data)
Run Code Online (Sandbox Code Playgroud)

recv'ing方面变得像:

dataToRead = struct.unpack("H", socket.read(2))[0]    
data = socket.read(dataToRead)
Run Code Online (Sandbox Code Playgroud)

这是套接字编程的常见设计模式.大多数设计扩展了线上结构以包括类型字段,因此您的接收方将变为:

type = socket.read(1)                                 # get the type of msg
dataToRead = struct.unpack("H", socket.read(2))[0]    # get the len of the msg
data = socket.read(dataToRead)                        # read the msg

if TYPE_FOO == type:
    handleFoo(data)

elif TYPE_BAR == type:
    handleBar(data)

else:
    raise UnknownTypeException(type)
Run Code Online (Sandbox Code Playgroud)

您最终得到了一种线上消息格式,如下所示:

struct {
     unsigned char type;
     unsigned short length;
     void *data;
}
Run Code Online (Sandbox Code Playgroud)

这样可以有效地解决线路协议面临无法预料的需求.它是一种类型 - 长度 - 值协议,您可以在网络协议中一次又一次地找到它.

  • 使用`struct.pack("H",len(data))`会产生一个重要结果:数据长度必须小于65536字节.您可以使用无符号长long而不是'Q`(最大大小= 18000 PB)来增加数据的最大允许大小. (2认同)