Почему соединение с сервером закрывается? - PullRequest
1 голос
/ 06 марта 2020

Я учусь создавать сервер в Python для игры.

В конце концов, мы вводим это l oop ниже. Я заменил несвязанный код комментариями для презентации. Он работает непрерывно, пока не будет получен определенный ответ от сервера (if split_reply[2] == "established":) или пока игрок не нажмет кнопку, чтобы перевести их в предыдущее меню.

def app_host():
    server_started = False
    connective_state = 'none'
    connect = True
    # stuff happening
    while connect:
        if not server_started:
            server = Server()
            host_address, host_port = server.get_host()
            server_started = True
            connective_state = 'host'
            net = Network(host_address, host_port)
        else:
             client_word = str(net.id) + ":" + "connective state" + ":" + connective_state
             reply = net.send(client_word)
             split_reply = reply.split(":")
             if split_reply[0] == net:
                 if split_reply[2] == "established":
                     connective_state = "established host"
                     app_setup()
             # other stuff happening
    if intro:
        app_intro()

Класс сервера следующий:

class Server:

    def __init__(self):
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.currentId = "0"
        self.connective_states = ["none", "none"]
        self.server_ip = socket.gethostbyname(socket.gethostname())

        try:
            self.s.bind((self.server_ip, 0))  # Binding to Port 0 allows the OS to select an available port
        except socket.error as e:
            print(str(e))

        self.server_port = self.s.getsockname()[1]

        self.s.listen(2)
        print(f"Server hosted on {self.server_ip}:{self.server_port}.")

        thread = threading.Thread(target=self.run_server, args=())
        thread.daemon = True  # Daemonize thread (if the game exits, shut down the server)
        thread.start()

    def run_server(self):
        while True:
            conn, addr = self.s.accept()
            print(f"Connected to {addr[0]}:{addr[1]}.")

            start_new_thread(self.threaded_client, (conn,))

    def get_host(self):
        return self.server_ip, self.server_port

    def threaded_client(self, conn):
        conn.send(str.encode(self.currentId))
        currentId = "1"
        while True:
            try:
                data = conn.recv(2048)
                reply = data.decode('utf-8')
                if not data:
                    conn.send(str.encode("Goodbye"))
                    break
                else:
                    print("Received: " + reply)
                    split_reply = reply.split(":")
                    socket_id = int(split_reply[0])

                    # The ifs below should have no effect on this issue, you can ignore them
                    if split_reply[1] == "connective state":
                        self.connective_states[socket_id] = split_reply[2]

                    if self.connective_states == ["host", "client"] or ["client", "host"]:
                    #if "host" in connective_states and "client" in connective_states:
                        print(f"Connective states are: {connective_states}")
                        reply = str(socket_id) + ":" + "connective state" + ":" + "established"
                        print(reply)
                        print("Connection established !")

                    elif split_reply[1] == "socket":
                        if split_reply[2] == "disconnect":
                            print(f"Received request to disconnect socket {split_reply[0]}.")
                            conn.close()

                conn.sendall(str.encode(reply))
            except:
                break
        print("Connection Closed")
        conn.close()

Сетевой класс:

class Network:

    def __init__(self, address, port):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.host = address

        self.port = port
        self.addr = (self.host, self.port)
        self.id = self.connect()

    def connect(self):
        self.client.connect(self.addr)
        return self.client.recv(2048).decode()

    def send(self, data):
        try:
            self.client.send(str.encode(data))
            reply = self.client.recv(2048).decode()
            return reply
        except socket.error as e:
            return str(e)

Во-первых, я использовал серверный класс в качестве скрипта, с threaded_client(conn) в качестве единственной функции, выполняемой как подпроцесс; и это будет работать нормально. Этот метод, тем не менее, каким-то образом достигает конца (print("Connection Closed") и закрывает соединение.

Почему это так?

Connection gets lost after the server starts.

1 Ответ

0 голосов
/ 07 марта 2020

Ну, не совсем ответ, который решает эту конкретную c проблему. Но ответ, поскольку он решает общую проблему при настройке сервера, тем не менее.

Я просто изменил свой server.py с класса на скрипт:

import socket
from _thread import *
import threading


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
currentId = "0"
connective_states = ["none", "none"]
server_ip = socket.gethostbyname(socket.gethostname())

try:
    s.bind((server_ip, 0))  # Binding to Port 0 allows the OS to select an available port
except socket.error as e:
    print(str(e))

server_port = s.getsockname()[1]
s.listen(2)
print(f"Server hosted on {server_ip}:{server_port}.")


def get_host():
    return server_ip, server_port


def threaded_client(conn):
    global currentId, connective_states
    conn.send(str.encode(currentId))
    currentId = "1"
    #reply = ''
    while True:
        try:
            data = conn.recv(2048)
            reply = data.decode('utf-8')
            if not data:
                conn.send(str.encode("Goodbye"))
                break
            else:
                print("Received: " + reply)
                split_reply = reply.split(":")
                socket_id = int(split_reply[0])

                if split_reply[1] == "connective state":
                    connective_states[socket_id] = split_reply[2]

                #if connective_states == ["host", "client"] or ["client", "host"]:
                if "host" in connective_states and "client" in connective_states:
                    print(f"Connective states are: {connective_states}")
                    reply = str(socket_id) + ":" + "connective state" + ":" + "established"
                    print(reply)
                    print("Connection established !")

                elif split_reply[1] == "socket":
                    if split_reply[2] == "disconnect":
                        print(f"Received request to disconnect socket {split_reply[0]}.")
                        conn.close()


            conn.sendall(str.encode(reply))
        except:
            break
    print("Connection Closed")
    conn.close()


def run_server():
    thread = threading.Thread(target=start_threaded_client, args=())
    thread.daemon = True  # Daemonize thread (if the game exits, shut down the server)
    thread.start()


def start_threaded_client():
    while True:
        conn, addr = s.accept()
        print(f"Connected to {addr[0]}:{addr[1]}.")

        start_new_thread(threaded_client, (conn,))

Затем, с помощью импортируя server.py в мой основной файл, код перед defs запускается автоматически. Я могу каким-то образом использовать трюк с if __name__ == '__main__':, чтобы остановить эту форму, но сейчас мне все равно. Затем я просто использую server.run_server ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...