import json import socketserver __VERSION__ = "0.0.1" # https://websockets.readthedocs.io/en/stable/reference/asyncio/server.html class LobbyMgr: __instance = None def __new__(cls): if cls.__instance is None: cls.__instance = LobbyMgr() return cls.__instance class LobbyHandler(socketserver.StreamRequestHandler): def handle(self): print(f" >>> New client {self.client} connected") exc = None try: self._handle_client() except Exception as e: exc = e finally: print(f" <<< Client {self.client} disconnected: {exc}") @property def client(self): return f"{':'.join(map(str, self.client_address))}" def _handle_client(self): self._send(type="hello", name="LobbySrv 3000", version=__VERSION__) while True: data = self.rfile.readline(10000).rstrip() print(f" <-- client {self.client} sent {repr(data)}") if not data.strip(): continue try: data = json.loads(data) except json.JSONDecodeError: self._send_error("Could not decode message, invalid json") continue if not isinstance(data, dict) or "cmd" not in data: self._send_error("Invalid format in json") continue print(f"{self.client_address[0]} wrote:", data) match data["cmd"]: case "quit": break case _: self._send_error("Unknown command") def _send(self, **kwargs): data = json.dumps(kwargs).encode() print(f" --> sending out to {self.client}: {data}") self.wfile.write(json.dumps(kwargs).encode() + b"\n") def _send_error(self, msg: str): self._send(type="error", message=msg) class LobbyServer(socketserver.ThreadingMixIn, socketserver.TCPServer): allow_reuse_address = True def main(): HOST, PORT = "localhost", 3784 with LobbyServer((HOST, PORT), LobbyHandler) as server: server.serve_forever() if __name__ == "__main__": main()