import socket from threading import Thread class SocketClient(Thread): __BLOCK_SIZE, __MAX_TIMES = 1024, 1024 * 10 def __init__(self, host: "str", port: "int"): super().__init__() self.__client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.__client.connect((host, port)) self.__handlers, self.__running = {"BROADCAST": self.__on_broad}, False def __on_broad(self, msg: "str"): raise NotImplementedError( "got a broadcast msg, but there are no handler for it.\n" "you should bind a message handler with 'on'." ) def on(self, event: "str"): def decorator(func): self.__handlers[event] = func return func return decorator def emit(self, event: "str", msg: "bytes"): self.__client.sendall(f"==EVENT:{event}==".encode("utf-8") + msg + b"==END==") def run(self) -> None: self.__running = True try: while self.__running: times = SocketClient.__MAX_TIMES cur = self.__client.recv(SocketClient.__BLOCK_SIZE) if cur.startswith(b"==EVENT:"): _e = cur[8:].find(b"==") event, cur = cur[8:_e + 8].decode("utf-8"), cur[_e + 10:] data = cur while not data.endswith(b"==END=="): cur = self.__client.recv(SocketClient.__BLOCK_SIZE) data, times = data + cur, times - 1 if times <= 0: break if data.endswith(b"==END=="): if event in self.__handlers.keys(): self.__handlers[event](data[:-7]) else: raise RuntimeError(f"bad ending in msg: {data[:20]}") finally: self.__client.close() def stop(self): self.__running = False