From e5e42aa6d9827962399bb4783c7b10988e4f610f Mon Sep 17 00:00:00 2001 From: steev Date: Thu, 4 Jan 2024 02:49:43 +0100 Subject: [PATCH] rewrote serverside netcode to support multiple connections at once --- .../Classes/System/Network/NetworkManger.py | 134 ++++++++++-------- .../Classes/System/Network/NetworkManager.py | 2 +- 2 files changed, 76 insertions(+), 60 deletions(-) diff --git a/Game Server/Classes/System/Network/NetworkManger.py b/Game Server/Classes/System/Network/NetworkManger.py index e9c599d..04c41d2 100644 --- a/Game Server/Classes/System/Network/NetworkManger.py +++ b/Game Server/Classes/System/Network/NetworkManger.py @@ -2,7 +2,7 @@ import json import socket import threading -from Classes.System.Network.Handler.EventHandler import UDPEventHandler, TCPEventHandler +from Classes.System.Network.EventHandler import UDPEventHandler, TCPEventHandler class NetworkManager: @@ -11,89 +11,105 @@ class NetworkManager: __Port:str __BufferSize:int = 1024 __udpSocket:socket + __users:list __UDPClientThread:threading.Thread __eventHandler: UDPEventHandler def __init__(self, Addr:str, Port:str): clientUdpSocket, clientUdpAddress = self.__udpSocket.accept() self.__Addr = Addr - self.__Port = Port + self.__Port = int(Port) + + self.__users = {} + self.__udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.__udpSocket.bind((self.__Addr, self.__Port)) self.__eventHandler = UDPEventHandler(clientUdpSocket) - self.__UDPClientThread = threading.Thread(target=self.handleUDPConnection, args=(clientUdpSocket, clientUdpAddress)) + + self.__UDPClientThread = threading.Thread(target=self.receive) self.__UDPClientThread.start() - # handles ticking the game loop server side converting data and passing of to the event handler - def handleUDPConnection(self, socket:socket, address): - # states that a connection has been established - print(f"Connected with {address}") - - # Communication with client + # handles incomming udp data + def receive(self): while True: - data = socket.recv(self.__bufferSize) - if not data: - break - - # decode message for handling + data, address = self.__udpSocket.recvfrom(self.__BufferSize) message = data.decode() messageJson = json.loads(message) + user = messageJson.get("user") - if messageJson["user"] in self.__users: - self.__eventHandler.handleUDPEvents(messageJson) - else: - break + if user not in self.__users: + self.__users[user] = address # Storing new user in dictionary - print(f"received message from {address}: {message}") + # Process the message and handle accordingly + self.__eventHandler.handleUDPEvents(messageJson) + print(f"Received message from {address}: {message}") + def broadcast(self, payload:dict): + for user_address in self.__users.values(): + self.__udpSocket.sendto(json.dumps(payload).encode(), user_address) - - def send(payload:bytes): - # todo: lookup how to send data - pass - + def send(self, payload:dict, user:str): + if user in self.__users: + self.__udpSocket.sendto(json.dumps(payload).encode(), self.__users[user]) + class TCP: - __Addr:str - __Port:str - __BufferSize:int = 1024 - __tcpSocket:socket - __TCPClientThread:threading.Thread - __eventHandler:TCPEventHandler - - def __init__(self, Addr:str, Port:str): - clientTcpSocket, clientTcpAddress = self.__tcpSocket.accept() + def __init__(self, Addr: str, Port: str): self.__Addr = Addr - self.__Port = Port - self.__eventHandler = TCPEventHandler(clientTcpSocket) - self.__TCPClientThread = threading.Thread(target=self.handleTCPConnection, args=(clientTcpSocket, clientTcpAddress)) - self.__TCPClientThread.start() + self.__Port = int(Port) + self.__users = {} + self.__tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.__tcpSocket.bind((self.__Addr, self.__Port)) + self.__tcpSocket.listen() - # handles ticking the game loop server side converting data and passing of to the event handler - def handleTCPConnection(self, socket:socket, address): - # states that a connection has been established - print(f"Connected with {address}") + self.__eventHandler = TCPEventHandler() - # Communication with client + self.__receive_thread = threading.Thread(target=self.accept_connections) + self.__receive_thread.start() + + def accept_connections(self): while True: - data = socket.recv(1024) - if not data: + client_tcp_socket, client_address = self.__tcpSocket.accept() + print(f"Connected with {client_address}") + self.__users[client_address] = client_tcp_socket + client_handler_thread = threading.Thread(target=self.receive, args=(client_tcp_socket, client_address)) + client_handler_thread.start() + + def receive(self, __tcpSocket: socket.socket, address): + while True: + try: + data = __tcpSocket.recv(1024) + if not data: + break + + message = data.decode() + message_json = json.loads(message) + user = message_json.get("user") + + if user not in self.__users: + self.__users[user] = address # Storing new user in dictionary + + # Process the message and handle accordingly + self.__eventHandler.handleTCPEvents(message_json) + print(f"Received message from {address}: {message}") + + except ConnectionResetError: + print(f"Connection with {address} closed.") + del self.__users[address] break - # decode message for handling - message = data.decode() - messageJson = json.loads(message) + def broadcast(self, payload: dict): + for user_socket in self.__users.values(): + user_socket.send(json.dumps(payload).encode()) - if messageJson["user"] in self.__users: - self.__eventHandler.handleTCPEvents(messageJson) - else: - break - - print(f"received message from {address}: {message}") - - - - def send(payload:bytes): - # todo: lookup how to send data - pass + def send(self, payload: dict, user_address): + if user_address in self.__users: + user_socket = self.__users[user_address] + user_socket.send(json.dumps(payload).encode()) + else: + print(f"User {user_address} is not connected.") + def close(self): + self.__tcpSocket.close() + tcp: TCP udp: UDP diff --git a/Game_Client/Classes/System/Network/NetworkManager.py b/Game_Client/Classes/System/Network/NetworkManager.py index d16d774..7850ebd 100644 --- a/Game_Client/Classes/System/Network/NetworkManager.py +++ b/Game_Client/Classes/System/Network/NetworkManager.py @@ -2,7 +2,7 @@ import json import socket import threading -from Classes.System.Network.Handler.EventHandler import TCPEventHandler, UDPEventHandler +from Game_Client.Classes.System.Network.EventHandler import TCPEventHandler, UDPEventHandler class NetworkManager: class UDP: