123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 |
- 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 <BROADCAST> 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
|