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_NICK: [self.on_nick],
ServerMessage.MSG_TOPIC: [self.on_topic],
ServerMessage.RAW: [self.on_raw],
}
self.receive()
def receive(self):
while line := self.__server_socket.recvline():
line = line.strip()
if line.startswith("PING"):
self.__server_socket.sendline("PONG " + line.split()[1])
continue
@ -244,14 +245,15 @@ class Client:
msg[0] = msg[0][1:]
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:
for func in self.__function_register[msg_type]:
func(msg_from, msg_to, message)
for func in self.__function_register['RAW']:
func(msg_from, msg_type, msg_to, message)
def register(self, msg_type: str, func: Callable[..., None]):
def subscribe(self, msg_type: str, func: Callable[..., None]):
if msg_type in self.__function_register:
self.__function_register[msg_type].append(func)
else:

View File

@ -40,32 +40,27 @@ class Socket:
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()
while b"\n" not in self.__recv_buffer and b"\r" not in self.__recv_buffer:
self.__recv_buffer = self.recv(256, blocking=False)
while b"\n" not in self.__recv_buffer:
self.__recv_buffer += self.recv(1024, blocking=False)
if time.time() - start <= timeout:
time.sleep(0.01) # release *some* resources
else:
break
newline = b"\r\n"
if newline not in self.__recv_buffer:
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):]
if b"\n" not in self.__recv_buffer:
return None
else:
self.__recv_buffer = b""
return ret
line = self.__recv_buffer[:self.__recv_buffer.index(b"\n")]
self.__recv_buffer = self.__recv_buffer[self.__recv_buffer.index(b"\n") + 1:]
return line.decode("UTF-8")
def close(self):
self.socket.close()