Я пытаюсь написать мой собственный TCP неблокирующий сервер для обработки нескольких длительных соединений с сокетами, а не для открытия множества потоков для их обработки.
Я написал свой слишком сложный, сложный в использовании синтаксис, но у меня возникают проблемы, когда я пытаюсь обнаружить закрытый сокет.
В обычном многопоточном сокет-сервере TCP я использовал бы обнаруженный b''
из функции socket.read(size)
, однако это невозможно с неблокирующим сокетом, поскольку он всегда будет возвращать BlockingIOError
Я также пытался перехватить эти следующие события
except BrokenPipeError:
conn.abort()
except ConnectionResetError:
conn.abort()
except ConnectionAbortedError:
conn.abort()
except socket.error:
conn.abort()
(conn
- это класс, в котором находится клиентский сокет и адрес из socket.accept()
)
Я не уверен, что делать, но вот очень упрощенная выдержка из моего кода:
def loop_listen(self):
while self.running == True:
cr, addr = self.server.accept()
crs = SocketHandler(self, cr, addr)
self.client_handler(crs)
self.connections.append(crs)
crs.events["open"]()
crs.cr.setblocking(0)
def loop_recv(self):
while self.running == True:
time.sleep(self.poll_time)
for conn in self.connections:
try:
data = conn.cr.recv(self.poll_size)
print(data)
if (data == b''):
conn.abort()
except BlockingIOError:
data = None
except BrokenPipeError:
conn.abort()
except ConnectionResetError:
conn.abort()
except ConnectionAbortedError:
conn.abort()
except socket.error:
conn.abort()
if (data != None):
conn.events["msg"](data)
(оба цикла являются отдельными потоками)
И васхотел, вот класс conn
class SocketHandler:
def __init__(self, server, cr, addr):
self.server = server
self.cr = cr
self.addr = addr
self.events = {"msg": emptyCallback, "close": "emptyCallback","open":emptyCallback}
self.cache = b""
def message(self, func):
self.events["msg"] = func
def close(self, func):
self.events["close"] = func
def open(self, func):
self.events["open"] = func
def send(self, data):
self.cr.send(data)
def abort(self):
self.cr.close()
self.events["close"]()
self.server.connections.remove(conn)
Это прекрасно работает в Windows, но в Ubuntu он не вызывает conn.abort()
.
Любая помощь будет принята с благодарностью.
Спасибо, Сэм.