Python 向客户端发送视频帧
我目前正在使用OpenCV阅读视频帧 在服务器端,我使用cPickle.dumps()序列化框架: 在客户端,我使用cPickle.load()序列化框架: 加载(数据)导致ValueError:不安全的字符串pickle。我做错了什么?我想阅读客户端的框架,并在tkinter窗口中显示它。我到处都查了9个多小时,但找不到解决办法 编辑1: 我也试过: 服务器端Python 向客户端发送视频帧,python,sockets,opencv,tkinter,Python,Sockets,Opencv,Tkinter,我目前正在使用OpenCV阅读视频帧 在服务器端,我使用cPickle.dumps()序列化框架: 在客户端,我使用cPickle.load()序列化框架: 加载(数据)导致ValueError:不安全的字符串pickle。我做错了什么?我想阅读客户端的框架,并在tkinter窗口中显示它。我到处都查了9个多小时,但找不到解决办法 编辑1: 我也试过: 服务器端 flag, frame = cap.read() if flag: size = sys.getsizeof(frame)
flag, frame = cap.read()
if flag:
size = sys.getsizeof(frame)
client_socket.send(str(size))
client_socket.sendall(cPickle.dumps(frame.tolist()))
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)
客户端
size = sock.recv(4000)
data = sock.recv(int(size))
frame = cPickle.loads(data) # Causes EOFError
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
编辑2:
服务器端
flag, frame = cap.read()
if flag:
size = sys.getsizeof(frame)
client_socket.send(str(size))
client_socket.sendall(cPickle.dumps(frame.tolist()))
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)
客户端
size = sock.recv(4000)
data = sock.recv(int(size))
frame = cPickle.loads(data) # Causes EOFError
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
您最多接收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
(比字符串串联更快)
现在,数据
可以加载到pickle中
注意:它不能解决self.ImageLabel.configure(image=frame)的问题。确保将所需的数组类型传递给此方法
编辑:现在你已经编辑了你的问题,你有更多的问题
- 首先,在使用pickle进行序列化之前计算对象的大小,这是不正确的,您应该使用
len(拾取的对象)
- 然后,您使用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
@Jean-Françoisfare cap.read()是OpenCV的函数。它给了我们一个机会object@Jean-Françoisfare cPickle.dumps(frame.tolist())在尝试cPickle.load(data)时会导致EOFError。我不确定self.ImageLabel.configure(image=frame)是否接受数据数组。在发送数据数组之前是否可以打印
frame
?这里似乎有些东西被破坏了…@Jean Françoisfare打印帧的结果:其中frame=cPickle.dumps(frame.tolist())您没有添加“…”,是吗?请查看我的编辑。服务器将发送许多帧。因此,在发送实际帧之前,我首先发送了帧的大小,但它仍然会导致错误。如果消息的大小是个问题,这难道不能解决这个问题吗?我使用struct尝试了您的解决方案。它仍然在给出ValueError:不安全的字符串pickle。请参见编辑2。是否可以在发射前和发射后打印尺寸?