【问题标题】:Getting pickle data truncated error while working with sockets and python使用套接字和 python 时出现 pickle 数据被截断错误
【发布时间】:2021-05-10 14:34:09
【问题描述】:

所以这里的问题。我正在尝试通过套接字发送大量二进制图像代码,这是 OpenCV 图像的腌制数据。我正在调整图像大小,然后将其从服务器发送到客户端。 当我将图像大小调整为(160,120) 时,我没有收到错误消息,但是当我将调整大小设置为(640,480) 时收到错误消息。我需要解决这个错误。请帮忙。

我的服务器.py

import socket, cv2, pickle, struct

# Socket Create
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host_name = socket.gethostname()
host_ip = socket.gethostbyname(host_name)
print('HOST IP:', host_ip)
port = 9999
socket_address = (host_ip, port)

# Socket Bind
server_socket.bind(socket_address)

# Socket Listen
server_socket.listen(5)
print("LISTENING AT:", socket_address)
Header_length = 20

# Socket Accept
while True:
    client_socket, addr = server_socket.accept()
    print('GOT CONNECTION FROM:', addr)
    if client_socket:
        vid = cv2.VideoCapture(0)

        while (vid.isOpened()):
            img, frame = vid.read()
            resized_frame = cv2.resize(frame , (640,480))
            a = pickle.dumps(resized_frame)
            message = f"{len(a):<{Header_length}}".encode('utf-8') + a
            client_socket.sendall(message)

            cv2.imshow('TRANSMITTING VIDEO', frame)
            key = cv2.waitKey(1) & 0xFF
            if key == ord('q'):
                client_socket.close()

我的客户.py

import socket, cv2, pickle, struct

# create socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host_name = socket.gethostname()
host_ip = socket.gethostbyname(host_name)  # paste your server ip address here
port = 9999
client_socket.connect((host_ip, port))  # a tuple
data = b""
payload_size = struct.calcsize("Q")
while True:
    recieved_data = client_socket.recv(20).decode('utf-8')
    if not recieved_data:
        continue
    frame_data = client_socket.recv(int(recieved_data))
    frame = pickle.loads(frame_data)
    cv2.imshow("RECEIVING VIDEO", frame)
    key = cv2.waitKey(1) & 0xFF
    if key == ord('q'):
        break
client_socket.close()

如果您想了解更多信息,请告诉引理。

【问题讨论】:

  • 错误是什么?

标签: python opencv sockets pickle


【解决方案1】:

.recv(n) 接收最多 n 个字节的数据,但可能(并且可能会)返回更少。检查收到的frame_data 的长度,如果小于n,则发出另一个.recv 的剩余部分,直到获得所有字节。

还可以查看socket.makefile,它将套接字包装在类似文件的对象中,您可以调用.read(n) 来准确读取n 个字节。

客户端/服务器之间对象的两种方式酸洗的完整示例:

from socket import *
import threading
import pickle

class ObjectStream:

    def __init__(self, sock):
        self.sock = sock
        self.writer = sock.makefile('wb')
        self.reader = sock.makefile('rb')
            
    # Objects are sent/received as a 4-byte big-endian integer of
    # the pickled object data length, followed by the pickled data.

    def get_obj(self):
        header = self.reader.read(4)
        if not header:
            return None
        length = int.from_bytes(header,'big')
        return pickle.loads(self.reader.read(length))

    def put_obj(self,obj):
        data = pickle.dumps(obj)
        header = len(data).to_bytes(4,'big')
        self.writer.write(header)
        self.writer.write(data)
        self.writer.flush()  # important!

    def close(self):
        if self.sock is not None:
            self.writer.close()
            self.reader.close()
            self.sock.close()
            self.sock = None
            self.writer = None
            self.reader = None

    # Support for 'with' to close everything.

    def __enter__(self):
        return self
    
    def __exit__(self,*args):
        self.close()

    # Support for no more references to ObjectStream

    def __del__(self):
        self.close()

def server():
    s = socket()
    s.bind(('',9999))
    s.listen()
    with s:
        while run:
            c,a = s.accept()
            print('server: connect from',a)
            with ObjectStream(c) as stream:
                while True:
                    obj = stream.get_obj()
                    print('server:',obj)
                    if obj is None: break
                    if isinstance(obj,list):
                        # reverse lists
                        stream.put_obj(obj[::-1])
                    elif isinstance(obj,dict):
                        # swap key/value in dictionaries
                        stream.put_obj({v:k for k,v in obj.items()})
                    else:
                        # otherwise, echo back same object
                        stream.put_obj(obj)
            print('server: disconnect from',a)

def client():
    s = socket()
    s.connect(('localhost',9999))
    with ObjectStream(s) as stream:
        stream.put_obj([1,2,3])
        print('client:',stream.get_obj())
        stream.put_obj({1:2,3:4,5:6})
        print('client:',stream.get_obj())
        stream.put_obj(12345)
        print('client:',stream.get_obj())

run = True  # Simple global flag to control server Thread
threading.Thread(target=server).start()
client()  # Server can handle only one client at a time as written.
client()  # But can serially serve clients.
run = False

输出:

server: connect from ('127.0.0.1', 52689)
server: [1, 2, 3]
client: [3, 2, 1]
server: {1: 2, 3: 4, 5: 6}
client: {2: 1, 4: 3, 6: 5}
server: 12345
client: 12345
server: None
server: disconnect from ('127.0.0.1', 52689)
server: connect from ('127.0.0.1', 52690)
server: [1, 2, 3]
client: [3, 2, 1]
server: {1: 2, 3: 4, 5: 6}
client: {2: 1, 4: 3, 6: 5}
server: 12345
client: 12345
server: None
server: disconnect from ('127.0.0.1', 52690)

【讨论】:

  • 我尝试了第一种方法。它工作正常。谢谢,但你能提供第二个例子吗,你能说出其中哪个更快
  • @KHAJAOWAISALI 查看更新。使用分析器查看哪个更快。
  • 兄弟,我没明白如何从客户端接收它。很抱歉打扰,但您能否提供一个代码的工作示例。我在这里遇到了一个新问题new question
  • @KHAJAOWAISALI c 是套接字。不管是哪一头,读法都一样
  • 哥那太好了,但是我有一个问题,如果服务器要向客户端发送数据怎么办?抱歉打扰了..
猜你喜欢
  • 1970-01-01
  • 2017-11-22
  • 2021-09-21
  • 2021-07-15
  • 1970-01-01
  • 2020-12-27
  • 2016-04-30
  • 2016-05-22
  • 1970-01-01
相关资源
最近更新 更多