Python 3.6中,套接字(Socket)的Pickle数据被截断。

25

我无法通过套接字发送我的numpy数组。我使用pickle,但我的客户端pickle崩溃并显示此错误:pickle数据被截断

我的服务器: 我创建了一个numpy数组,想用pickle将其发送到我的客户端(它可以工作)

import socket, pickle
import numpy as np
from PIL import ImageGrab
import cv2


while(True):
    HOST = 'localhost'
    PORT = 50007
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 4096)
    s.bind((HOST, PORT))
    s.listen(1)
    conn, addr = s.accept()
    print ('Connected by', addr)

    arr = np.array([[0, 1], [2, 3]])
    printscreen_pil=ImageGrab.grab(bbox=(10,10,500,500))
    img = np.array(printscreen_pil) ## Transform to Array
    
    data_string = pickle.dumps(img)
    conn.send(data_string)

    msg_recu = conn.recv(4096)
    print(msg_recu.decode())

    conn.close()

我的客户有我的numpy数组,但我无法使用pickle加载。我遇到了这个错误。

import socket, pickle
import numpy as np

HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

msg_a_envoyer = "hello".encode()
s.send(msg_a_envoyer)


while 1:
    data = s.recv(4096)
    if not data: break
    data_arr = pickle.loads(data)
    print (data_arr)
s.close()

但是你只收到了4096位吗? - Willem Van Onsem
2个回答

26

问题在于,如果选取的数据大小超过4096,则您只会收到选取数据的前半部分(因此您看到的是“选取数据已截断”消息)。

您必须在接收完成后将数据追加并进行选取处理,例如像这样:

data = b""
while True:
    packet = s.recv(4096)
    if not packet: break
    data += packet

data_arr = pickle.loads(data)
print (data_arr)
s.close()

增加一个字节对象的性能不是很好,更好的方法是将部分内容存储在对象列表中,然后使用join连接。更快的变体:

data = []
while True:
    packet = s.recv(4096)
    if not packet: break
    data.append(packet)
data_arr = pickle.loads(b"".join(data))
print (data_arr)
s.close()

5
简单来说,你试图加载的文件并不完整。可能是由于你没有正确地下载它,或者你的pickle文件已经损坏了。你可以创建一个新的pickle文件来解决这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接