Проблема с pickle.loads () - закончился ввод - PullRequest
0 голосов
/ 08 апреля 2020

Я пытаюсь сделать небольшую многопользовательскую игру и, следовательно, нужно отправлять объекты. Создал сервер и клиент, и все работает для отправки байтов, например (str("").encode(utf-8)). Но когда я попытался использовать рассол, я начал сталкиваться с проблемами. Любая помощь и объяснение, где я делаю ошибки, очень ценится. Спасибо! Server.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)

Client.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)

Я также пытался поместить l oop в send_object (), но затем после нескольких успешных поступлений я получаю :

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

1 Ответ

0 голосов
/ 14 апреля 2020

После некоторых исследований выясняется, что перед тем, как пытаться вскрыть объект, вам сначала нужно проверить, не получено ли полученное сообщение. Потому что сервер постоянно пытается получить сообщение от клиента, но это другая проблема. Изменение кода в 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 не будет отправлено клиентом, оно будет использовать много процессорного времени (упомянутая выше проблема)

...