首页 > 解决方案 > pickle.loads() 的问题 - 输入不足

问题描述

我正在尝试制作一个小型多人游戏,因此需要发送对象。已经创建了服务器和客户端,一切都在发送字节,例如(str("").encode(utf-8))

但是当我尝试使用泡菜时,我开始遇到问题。我在下面犯了任何错误吗?

服务器.py:

import socket
import threading
import pickle

HEADER = 8          #Contains info about incoming msg SIZE! first 8 bytes contains size
FORMAT = "utf-8"
PORT = 5558
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
DISCONNECT_MSG = "!Disconnect"

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(ADDR)

def handle_client(client_socket, client_addr):
    print(f"[NEW CONNECTION] {client_addr} connected!")

    while True:
        try:
            msg = pickle.loads(client_socket.recv(2048))
            print(f"[RECEIVED] {client_addr} - {msg}")
            if msg == DISCONNECT_MSG:
                print(f"[DISCONNECTED] client {client_addr} has disconnected")
                client_socket.close()
                return False
        except socket.error as e:
            print(e)

def start_server(server):
    server.listen()
    print("[STARTED] server is online!")

    while True:
        client_socket, client_addr = server.accept()
        thread = threading.Thread(target=handle_client, args=(client_socket, client_addr))
        thread.start()
        print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}")

print("[STARTING] server is starting...")
start_server(server_socket)

客户端.py

import socket
import pickle

HEADER = 8
FORMAT = "utf-8"
PORT = 5558
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
DISCONNECT_MSG = "!Disconnect"

class Client:

    def __init__(self):
        self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def connect_to_server(self, server_address):
        """
        :param server_address: tuple(IP, PORT)
        :return:
        """
        self.get_client_socket().connect(server_address)

    def get_client_socket(self):
        return self.client_socket

    def send_object(self, object):
            msg = pickle.dumps(object)
            self.get_client_socket().sendall(msg)

client = Client()
client.connect_to_server(ADDR)
d = "1"
client.send_object(d)
#client.send_object(DISCONNECT_MSG)

我也尝试将 while 循环放入 send_object() 但在成功接收几次后我得到:

msg = pickle.loads(client_socket.recv(2048))
_pickle.UnpicklingError: invalid load key, '\x00'.

标签: pythonsocketspickle

解决方案


经过一些研究,似乎在尝试解开对象之前,您首先需要检查收到的消息是否不是 None。因为服务器不断尝试从客户端接收消息,但这是另一个问题。server.py 中的代码修改:

def handle_client(client_socket, client_addr):
    print(f"[NEW CONNECTION] {client_addr} connected!")

        while True:
        try:
            msg = client_socket.recv(2048)
            if msg:
                new_msg = pickle.loads(msg[HEADER:])
                print(f"[RECEIVED] {client_addr} - {new_msg}")
                if msg == DISCONNECT_MSG:
                    print(f"[DISCONNECTED] client {client_addr} has disconnected")
                    client_socket.close()
                    return False
        except socket.error as e:
            print(e)

注意 -> 直到 DISCONNECT 消息没有从客户端发送,它将使用很多处理器时间(上面提到的问题)


推荐阅读