【问题标题】:Why does the connection to the server close?为什么与服务器的连接关闭?
【发布时间】:2020-06-19 11:13:57
【问题描述】:

我正在学习如何用 Python 为游戏创建服务器。

最终,我们进入下面的这个循环。我用 cmets 替换了不相关的代码以进行演示。它会持续运行,直到收到来自服务器 (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()

Server 类如下:

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") 并关闭连接。

这是为什么呢?

【问题讨论】:

    标签: python-3.x sockets server


    【解决方案1】:

    嗯,不完全是解决这个特定问题的答案。但是,它解决了设置服务器的一般问题。

    我刚刚将 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()。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-31
      • 1970-01-01
      相关资源
      最近更新 更多