way better (and much quicker) solution to receive lines from sockets

This commit is contained in:
Stefan Harmuth 2021-12-12 08:25:47 +01:00
parent d806c838c4
commit ec059d5354
2 changed files with 21 additions and 24 deletions

View File

@ -224,12 +224,13 @@ class Client:
ServerMessage.MSG_QUIT: [self.on_quit], ServerMessage.MSG_QUIT: [self.on_quit],
ServerMessage.MSG_NICK: [self.on_nick], ServerMessage.MSG_NICK: [self.on_nick],
ServerMessage.MSG_TOPIC: [self.on_topic], ServerMessage.MSG_TOPIC: [self.on_topic],
ServerMessage.RAW: [self.on_raw],
} }
self.receive() self.receive()
def receive(self): def receive(self):
while line := self.__server_socket.recvline(): while line := self.__server_socket.recvline():
line = line.strip()
if line.startswith("PING"): if line.startswith("PING"):
self.__server_socket.sendline("PONG " + line.split()[1]) self.__server_socket.sendline("PONG " + line.split()[1])
continue continue
@ -244,14 +245,15 @@ class Client:
msg[0] = msg[0][1:] msg[0] = msg[0][1:]
message = " ".join(msg) message = " ".join(msg)
if ServerMessage.RAW in self.__function_register:
for func in self.__function_register[ServerMessage.RAW]:
func(msg_from, msg_type, msg_to, message)
if msg_type in self.__function_register: if msg_type in self.__function_register:
for func in self.__function_register[msg_type]: for func in self.__function_register[msg_type]:
func(msg_from, msg_to, message) func(msg_from, msg_to, message)
for func in self.__function_register['RAW']: def subscribe(self, msg_type: str, func: Callable[..., None]):
func(msg_from, msg_type, msg_to, message)
def register(self, msg_type: str, func: Callable[..., None]):
if msg_type in self.__function_register: if msg_type in self.__function_register:
self.__function_register[msg_type].append(func) self.__function_register[msg_type].append(func)
else: else:

View File

@ -40,32 +40,27 @@ class Socket:
self.send(line) self.send(line)
def recvline(self, timeout: int = 10) -> str: def recvline(self, timeout: int = 0) -> Union[str, None]:
"""
Receive exactly one text line (delimiter: newline "\n" or "\r\n") from the socket.
:param timeout: wait at most TIMEOUT seconds for a newline to appear in the buffer
:return: Either a str containing a line received or None if no newline was found
"""
start = time.time() start = time.time()
while b"\n" not in self.__recv_buffer and b"\r" not in self.__recv_buffer: while b"\n" not in self.__recv_buffer:
self.__recv_buffer = self.recv(256, blocking=False) self.__recv_buffer += self.recv(1024, blocking=False)
if time.time() - start <= timeout: if time.time() - start <= timeout:
time.sleep(0.01) # release *some* resources time.sleep(0.01) # release *some* resources
else: else:
break break
newline = b"\r\n" if b"\n" not in self.__recv_buffer:
if newline not in self.__recv_buffer: return None
newline = b"\n"
if newline not in self.__recv_buffer:
newline = b"\r"
if newline not in self.__recv_buffer:
ret = self.__recv_buffer.decode("UTF-8")
self.__recv_buffer = b""
return ret
ret = self.__recv_buffer[:self.__recv_buffer.index(newline)].decode("UTF-8")
if len(self.__recv_buffer) - len(newline) > self.__recv_buffer.index(newline):
self.__recv_buffer = self.__recv_buffer[self.__recv_buffer.index(newline) + len(newline):]
else: else:
self.__recv_buffer = b"" line = self.__recv_buffer[:self.__recv_buffer.index(b"\n")]
self.__recv_buffer = self.__recv_buffer[self.__recv_buffer.index(b"\n") + 1:]
return ret return line.decode("UTF-8")
def close(self): def close(self):
self.socket.close() self.socket.close()