我目前正在使用OpenCV来阅读视频帧。
在服务器端,我使用cPickle.dumps()来序列化帧:
flag, frame = cap.read()
frame = cPickle.dumps(frame)
client_socket.sendall(frame)
在客户端,我使用cPickle.loads()序列化帧:
data = sock.recv(4000)
frame = cPickle.loads(data) # ValueError: insecure string pickle
self.ImageLabel.configure(image=frame) # Want to show the frame in Tkinter
self.ImageLabel.image = frame
self.ImageLabel.grid(row=4, columnspan=40)
cPickle.loads(data)导致ValueError:不安全的字符串pickle。我究竟做错了什么?我想在客户端读取框架并在tkinter窗口中显示它。我已经查看了每个地方超过9个小时,但无法找到解决方案。
编辑1:
我也试过这个:
服务器端
flag, frame = cap.read()
if flag:
size = sys.getsizeof(frame)
client_socket.send(str(size))
client_socket.sendall(cPickle.dumps(frame.tolist()))
客户端
size = sock.recv(4000)
data = sock.recv(int(size))
frame = cPickle.loads(data) # Causes EOFError
编辑2: 服务器端
flag, frame = cap.read()
if flag:
frame = cPickle.dumps(frame)
size = len(frame)
p = struct.pack("I", size)
client_socket.send(p)
client_socket.sendall(frame)
客户端
sizep = sock.recv(struct.calcsize("I"))
data_size = struct.unpack("I",sizep)
print type (data_size) # tuple - has (11026730, )
data = sock.recv(int(data_size[0]))
frame = cPickle.loads(data) # ValueError: insecure string pickle
答案 0 :(得分:1)
您使用以下
接收最多4000字节的数据data = sock.recv(4000)
但是信息要大于此。您必须完全阅读该消息或它被截断,这解释了pickle错误。例如,这样做:
packets = []
while True:
b = sock.recv(4096)
if b:
packets.append(b)
else:
break
data = "".join(packets)
将读取套接字,直到无法读取为止。我把每个数据包放在一个列表中,所以我之后可以使用str.join
(比字符串连接更快)。
现在可以将data
加载到pickle中。
注意:它无法确定self.ImageLabel.configure(image=frame)
。确保将预期的数组类型传递给此方法。
编辑:既然您已经编辑了问题,那么您还有更多问题。
len(picked object)
recv(4000)
读取大小:你只是通过这样做消耗了缓冲区的一部分,而你不知道整数的大小是否为字符串,因此大小问题没有解决。如果您需要先发送尺寸,则需要使用struct.pack
对其进行编码,然后使用struct.unpack
在客户端对其进行解码。这是我的提案(您需要导入struct
):
服务器端:
flag, frame = cap.read()
if flag:
data = cPickle.dumps(frame) # serialize
data_size = len(data) # nb of bytes of serialized data
p = struct.pack("I",data_size) # encode size
client_socket.send(p) # send encoded size
client_socket.sendall(data) # send serialized data
客户方:
sizep = sock.recv(struct.calcsize("I")) # first thing: recieved encoded size
data_size = struct.unpack("I",sizep) # decode size
data = sock.recv(data_size) # read data size
frame = cPickle.loads(data) # unserialize