在流中重新组装 pickled Python 对象的最安全方法是什么?
What is the safest way to reassemble pickled Python objects in a stream?
我目前正在通过两个 运行 程序之间的套接字发送 pickled Python (3.8) 对象。我有一个字节缓冲区,我想在接收端将其重建为相应的对象。
据我了解,socket.recv
方法不能保证捕获所有发送的字节,调用者需要再次调用 socket.recv
以获取其余数据。因此,在任何给定时间,我的缓冲区都可能包含部分数据包。
此外,由于我使用线程,在检查缓冲区之前我可能会收到多条消息。
这是我的问题:
鉴于我正在接收任意长度的字节流,其中可能包含少于或多于一个 pickle 对象,重新组合它们的最佳方法是什么? 有没有我可以用作终止符的字符保证不会与 pickle
?
冲突
Is there a character I can use as a terminator that is guaranteed to not conflict with pickle?
遗憾的是没有。 Pickle 以二进制形式打包数据,因此任何字节序列都可以出现在 pickled object.
中
what is the best way to reassemble them?
处理此类问题时最常见(也可能是最简单)的做法是发送一个 fixed-size header 指示要发送的数据大小收到。
您可以使用 struct.pack()
创建一个 8 字节 header 包含腌制大小的二进制表示(作为 8 字节 network-endian 无符号整数)object,并在实际数据之前发送。在接收端,您将首先收到 8 个字节 header,然后对其进行解码以了解发送的数据的大小,最后准确接收到该字节数。
这是一个(简化的)示例:
发件人:
class Example:
pass
data = pickle.dumps(Example())
size = len(data)
header = struct.pack("!Q", size)
# open socket...
sock.sendall(header)
sock.sendall(data)
接收者:
class Example:
pass
def receive_exactly(sock, n):
data = b''
while n > 0:
chunk = sock.recv(n)
n -= len(chunk)
data += chunk
return data
# open socket...
header = receive_exactly(sock, 8)
size = struct.unpack("!Q", header)[0]
data = receive_exactly(sock, size)
e = pickle.loads(data)
请注意,以上两个片段仅作为简单示例,您在使用 sendall()
和 recv()
时应进行适当的错误检查和处理。
我目前正在通过两个 运行 程序之间的套接字发送 pickled Python (3.8) 对象。我有一个字节缓冲区,我想在接收端将其重建为相应的对象。
据我了解,socket.recv
方法不能保证捕获所有发送的字节,调用者需要再次调用 socket.recv
以获取其余数据。因此,在任何给定时间,我的缓冲区都可能包含部分数据包。
此外,由于我使用线程,在检查缓冲区之前我可能会收到多条消息。
这是我的问题:
鉴于我正在接收任意长度的字节流,其中可能包含少于或多于一个 pickle 对象,重新组合它们的最佳方法是什么? 有没有我可以用作终止符的字符保证不会与 pickle
?
Is there a character I can use as a terminator that is guaranteed to not conflict with pickle?
遗憾的是没有。 Pickle 以二进制形式打包数据,因此任何字节序列都可以出现在 pickled object.
中what is the best way to reassemble them?
处理此类问题时最常见(也可能是最简单)的做法是发送一个 fixed-size header 指示要发送的数据大小收到。
您可以使用 struct.pack()
创建一个 8 字节 header 包含腌制大小的二进制表示(作为 8 字节 network-endian 无符号整数)object,并在实际数据之前发送。在接收端,您将首先收到 8 个字节 header,然后对其进行解码以了解发送的数据的大小,最后准确接收到该字节数。
这是一个(简化的)示例:
发件人:
class Example: pass data = pickle.dumps(Example()) size = len(data) header = struct.pack("!Q", size) # open socket... sock.sendall(header) sock.sendall(data)
接收者:
class Example: pass def receive_exactly(sock, n): data = b'' while n > 0: chunk = sock.recv(n) n -= len(chunk) data += chunk return data # open socket... header = receive_exactly(sock, 8) size = struct.unpack("!Q", header)[0] data = receive_exactly(sock, size) e = pickle.loads(data)
请注意,以上两个片段仅作为简单示例,您在使用 sendall()
和 recv()
时应进行适当的错误检查和处理。