fixed issue crashing connections and added system logger

This commit is contained in:
steev 2024-01-14 17:55:35 +01:00
parent 677552a617
commit 15cce52aea
16 changed files with 93 additions and 81 deletions

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"cSpell.ignoreWords": [
"posx"
]
}

View File

@ -9,13 +9,17 @@ class GameManager:
__state:str __state:str
__round:str __round:str
def __init__(self): def __init__(self, logger):
self.__players = {} self.__players = {}
self.__playingPlayer = None self.__playingPlayer = None
self.__state = "waiting" self.__state = "waiting"
self.__round = "none" self.__round = "none"
self.logger = logger
pass pass
def getLogger(self):
return self.logger
# game round management # game round management
# this section manages the flow of rounds this should inherit itself # this section manages the flow of rounds this should inherit itself
# ============================================================================= # =============================================================================

View File

@ -0,0 +1,18 @@
import logging
class Logger:
def __init__(self, filename):
logging.basicConfig(filename=filename,
filemode='a',
format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
datefmt='%H:%M:%S',
level=logging.DEBUG)
def info(self, message):
print(message)
logging.info(message)
def error(self, message):
print(message)
logging.error(message)

View File

@ -13,15 +13,7 @@ class TCPEventHandler:
# handles passing of event data to the right functions # handles passing of event data to the right functions
def handleTCPEvents(self, event, gameManager:GameManager, address): def handleTCPEvents(self, event, gameManager:GameManager, address):
pass gameManager.getLogger().info(f"incommingevent {event}")
class UDPEventHandler:
__udpSocket:socket
def __init__(self, socket:socket, gameManager:GameManager):
self.__udpSocket = socket
def handleUDPEvents(self, event):
if event["event"] == "PlaceCard": if event["event"] == "PlaceCard":
pass pass
elif event["event"] == "MoveCard": elif event["event"] == "MoveCard":
@ -36,3 +28,4 @@ class UDPEventHandler:
pass pass
elif event["event"] == "ActivateMonsterCard": elif event["event"] == "ActivateMonsterCard":
pass pass
pass

View File

@ -1,4 +1,5 @@
import json import json
import signal
import socket import socket
import sys import sys
import threading import threading
@ -9,56 +10,6 @@ from Classes.System.Network.EventHandler import UDPEventHandler, TCPEventHandler
from Classes.System.World import World from Classes.System.World import World
class NetworkManager: class NetworkManager:
#class UDP:
# __Addr:str
# __Port:str
# __BufferSize:int = 1024
# __udpSocket:socket
# __users:dict
# __eventHandler: UDPEventHandler
# __UDPClientThread:threading.Thread
# __gameManager:GameManager
#
# def __init__(self, Addr:str, Port:str, gameManager:GameManager):
# self.__Addr = Addr
# self.__Port = int(Port)
# self.__gameManager = gameManager
# self.__users = {}
# self.__eventHandler = {}
# self.__udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#
# try:
# self.__udpSocket.bind((self.__Addr, self.__Port))
# except OSError as e:
# print(f"Error binding UDP socket: {e}")
#
# self.__UDPClientThread = threading.Thread(target=self.receive)
# self.__UDPClientThread.start()
#
# # handles incoming udp data
# def receive(self):
# while True:
# data, address = self.__udpSocket.recvfrom(self.__BufferSize)
# message = data.decode()
# messageJson = json.loads(message)
# user = messageJson.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.handleUDPEvents(messageJson, self.__serverWorld)
# 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(self, payload:dict, user:str):
# if user in self.__users:
# self.__udpSocket.sendto(json.dumps(payload).encode(), self.__users[user])
#
class TCP: class TCP:
__Addr:str __Addr:str
__Port:str __Port:str
@ -70,40 +21,49 @@ class NetworkManager:
__gameManager:GameManager __gameManager:GameManager
def __init__(self, Addr:str, Port:str, gameManager:GameManager): def __init__(self, Addr:str, Port:str, gameManager:GameManager):
gameManager.getLogger().info("starting up network manager")
self.running = True self.running = True
self.__Addr = Addr self.__Addr = Addr
self.__Port = int(Port) self.__Port = int(Port)
self.__gameManager = gameManager self.__gameManager = gameManager
self.__eventHandler = {} self.__eventHandler = {}
gameManager.getLogger().info("starting up tcp server")
self.__tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.__tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__tcpSocket.bind((self.__Addr, self.__Port)) self.__tcpSocket.bind((self.__Addr, self.__Port))
self.__tcpSocket.listen() self.__tcpSocket.listen()
gameManager.getLogger().info("starting up thread for client socket accepting")
self.__TCPClientThread = threading.Thread(target=self.accept_connections) self.__TCPClientThread = threading.Thread(target=self.accept_connections)
self.__TCPClientThread.daemon = True
self.__TCPClientThread.start() self.__TCPClientThread.start()
def accept_connections(self): def accept_connections(self):
while self.running: while self.running:
try: try:
client_tcp_socket, client_address = self.__tcpSocket.accept() client_tcp_socket, client_address = self.__tcpSocket.accept()
print(f"Connected with {client_address}") self.__gameManager.getLogger().info(f"Connected with {client_address}")
self.__gameManager.getPlayers()[client_address] = client_tcp_socket self.__gameManager.getPlayers()[client_address] = client_tcp_socket
self.__eventHandler[client_address] = TCPEventHandler(client_tcp_socket) self.__eventHandler[client_address] = TCPEventHandler(client_tcp_socket)
client_handler_thread = threading.Thread( client_handler_thread = threading.Thread(
target=self.receive, target=self.receive,
args=(client_tcp_socket, client_address) args=(client_tcp_socket, client_address)
) )
self.__gameManager.getLogger().info(f"starting client handler thread for client at address {client_address}")
client_handler_thread.daemon = True
client_handler_thread.start() client_handler_thread.start()
except Exception as e: except Exception as e:
print(f"tcp socket failed to accept connection due to error: {e}") self.__gameManager.getLogger().error(f"tcp socket failed to accept connection due to error: {e}")
pass pass
client_handler_thread.join()
def receive(self, client_socket, client_address): def receive(self, client_socket, client_address):
while self.running: while self.running:
try: try:
data = client_socket.recv(self.__BufferSize) data = client_socket.recv(self.__BufferSize)
if not data: if not data:
print(f"Connection with {client_address} closed.") self.__gameManager.getLogger().info(f"Connection with {client_address} closed.")
break break
message = data.decode() message = data.decode()
@ -114,21 +74,23 @@ class NetworkManager:
# if enough users for a round are connected the server has to start the game # if enough users for a round are connected the server has to start the game
if user not in self.__gameManager.getPlayers(): if user not in self.__gameManager.getPlayers():
if messageJson["event"] == "login": if messageJson["event"] == "login":
self.logger.__gameManager.getLogger().info("user logging in")
self.logger.__gameManager.getLogger().info("task passed off to gameManager")
self.__gameManager.addPlayers(Player(messageJson["username"], messageJson["deck"]), client_socket, client_address) self.__gameManager.addPlayers(Player(messageJson["username"], messageJson["deck"]), client_socket, client_address)
print(f"connected users {len(self.__gameManager.getPlayers())}") self.__gameManager.getLogger().info(f"connected users {len(self.__gameManager.getPlayers())}")
self.__eventHandler[client_address].handleTCPEvents(messageJson, self.__gameManager, client_address) self.__eventHandler[client_address].handleTCPEvents(messageJson, self.__gameManager, client_address)
print(f"Received message from {client_address}: {message}") self.__gameManager.getLogger().info(f"Received message from {client_address}: {message}")
except socket.error as e: except socket.error as e:
if e.errno == 10054: if e.errno == 10054:
print(f"Connection with {client_address} forcibly closed by remote host.") self.__gameManager.getLogger().error(f"Connection with {client_address} forcibly closed by remote host.")
break break
print(f"Socket error receiving data from {client_address}: {e}") self.__gameManager.getLogger().error(f"Socket error receiving data from {client_address}: {e}")
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
print(f"JSON decoding error receiving data from {client_address}: {e}") self.__gameManager.getLogger().error(f"JSON decoding error receiving data from {client_address}: {e}")
except Exception as e: except Exception as e:
print(f"Error receiving data from {client_address}: {e}") self.__gameManager.getLogger().error(f"Error receiving data from {client_address}: {e}")
def broadcast(self, payload:dict): def broadcast(self, payload:dict):
for user in self.__gameManager.getPlayers().values(): for user in self.__gameManager.getPlayers().values():
@ -140,11 +102,19 @@ class NetworkManager:
if user in players and "socket" in players[user]: if user in players and "socket" in players[user]:
players[user]["socket"].send(json.dumps(payload).encode()) players[user]["socket"].send(json.dumps(payload).encode())
else: else:
print(f"user '{user}' or socket was not found 'socket' failed to send data.") self.__gameManager.getLogger().error(f"user '{user}' or socket was not found 'socket' failed to send data.")
def stop(self):
self.__TCPClientThread.join() # Wait for the thread to finish before exiting
tcp: TCP tcp: TCP
# udp: UDP # udp: UDP
def __init__(self, Addr:str, TCPPort:str, UDPPort:str, gameManager:GameManager): def __init__(self, Addr:str, TCPPort:str, UDPPort:str, gameManager:GameManager):
self.tcp = self.TCP(Addr, TCPPort, gameManager) self.tcp = self.TCP(Addr, TCPPort, gameManager)
# self.udp = self.UDP(Addr, UDPPort, gameManager) signal.signal(signal.SIGINT, self.handle_interrupt) # Register the signal handler
def handle_interrupt(self, signum, frame):
self.__gameManager.getLogger().info("Received keyboard interrupt. Stopping the server.")
self.tcp().stop()
sys.exit(0)

View File

@ -6,6 +6,7 @@ from Classes.System.GameManager import GameManager
from Classes.System.Network.NetworkManger import NetworkManager from Classes.System.Network.NetworkManger import NetworkManager
from Classes.System.PlayerManager import Player from Classes.System.PlayerManager import Player
from Classes.System.World import World from Classes.System.World import World
from Classes.System.Logger import Logger
class Server: class Server:
@ -17,16 +18,23 @@ class Server:
networkManager:NetworkManager networkManager:NetworkManager
def __init__(self, address:str, tcpPort:str, udpPort:str): def __init__(self, address:str, tcpPort:str, udpPort:str, logger:Logger):
self.__address = address self.__address = address
self.__tcpPort = tcpPort self.__tcpPort = tcpPort
self.__udpPort = udpPort self.__udpPort = udpPort
self.__world = World() self.__world = World()
self.__gameManager = GameManager() self.logger = logger
self.logger.info("starting up game manager")
self.__gameManager = GameManager(logger)
self.logger.info("preparing to start server")
self.startServer(self.__gameManager) self.startServer(self.__gameManager)
# handles starting the server and assigning socket values to the local reference # handles starting the server and assigning socket values to the local reference
def startServer(self, gameManager:GameManager): def startServer(self, gameManager:GameManager):
self.logger.info("starting up network manager")
self.__networkManager = NetworkManager(self.__address, self.__tcpPort, self.__udpPort, gameManager) self.__networkManager = NetworkManager(self.__address, self.__tcpPort, self.__udpPort, gameManager)
def getNetworkManager(self) -> NetworkManager:
return self.__networkManager

View File

@ -1,7 +1,18 @@
import logging
import os import os
import random
import string
import sys import sys
from Classes.System.Server import Server from Classes.System.Server import Server
from Classes.System.Logger import Logger
def get_random_string(length) -> str:
# choose from all lowercase letter
letters = string.ascii_lowercase
result_str = ''.join(random.choice(letters) for i in range(length))
print("Random string of length", length, "is:", result_str)
return result_str
def main(): def main():
# retrieves host data from environment # retrieves host data from environment
@ -9,9 +20,11 @@ def main():
TCPPORT = "54322" TCPPORT = "54322"
UDPPORT = "54323" UDPPORT = "54323"
Server(HOST, TCPPORT, UDPPORT) logger = Logger("log/"+get_random_string(8)+".log")
logger.info("starting up server")
server = Server(HOST, TCPPORT, UDPPORT, logging)
server.getNetworkManager().tcp.stop()
sys.exit(0) sys.exit(0)
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -13,7 +13,8 @@ def PlaceCard(tcpClient, card):
"event":"placecard", "event":"placecard",
"card": card.getID(), "card": card.getID(),
"type": card.getType(), "type": card.getType(),
"pos": card.getPos(), "posx": card.getPos().x,
"posy": card.getPos().y,
} }
tcpClient.send(payload) tcpClient.send(payload)
@ -27,7 +28,7 @@ def CardPlaced(world:World, card:int, type:str, owner:str, pos:pygame.Vector2, i
world.spawnSpellCard(f"Assets/Cards/{card}/", pos, inputHandler, owner) world.spawnSpellCard(f"Assets/Cards/{card}/", pos, inputHandler, owner)
pass pass
elif type == "TrapCard": elif type == "TrapCard":
world.spawmTrapCard(f"Assets/Cards/{card}/", pos, inputHandler, owner) world.spawnTrapCard(f"Assets/Cards/{card}/", pos, inputHandler, owner)
pass pass
pass pass

View File

@ -117,7 +117,7 @@ class App:
if event.button == 1: # Wenn linke Maustaste losgelassen wird if event.button == 1: # Wenn linke Maustaste losgelassen wird
for card in self.__world.getCards(): for card in self.__world.getCards():
card.setDragging(False) card.setDragging(False)
card.setState("placed") # card.setState("placed")
# TODO: send place card event to server # TODO: send place card event to server
# resets the currently selected card in order to prevent it getting moved # resets the currently selected card in order to prevent it getting moved
try: try: