Я видел несколько постов, в которых обсуждается проблема обнаружения закрытых сокетов.Большинство рекомендуют выбрать, что я сейчас и использую.Тем не менее, я вижу поведение, которое я не понимаю, и ищу совета.
У меня есть цикл обработки событий, работающий на сервере, который проверяет сообщения каждые 1/30 секунды (я использую неблокировка розеток).После получения сообщений сервер выполняет все необходимые задачи и добавляет исходящие сообщения в очередь отправки.В конце обновления я отправляю сообщения клиентам:
read, write, error = select.select([], self._CLIENTS.values(), [])
for sock in write:
addr = sock.getpeername()
if addr in self.__send_queue:
for key in self.__send_queue[addr]:
for msg in reversed(self.__send_queue[addr][key]):
self._send(self._CLIENTS[addr], msg.encode())
self._rmv_msg_from_queue(self.__send_queue, addr, key)
, где _CLIENTS
содержит пару addr:sock
, key
- заголовок сообщения, указывающий, к чему относится сообщение,и __send_queue
хранит список всех исходящих сообщений и заполняется после прочтения входящих сообщений.
Моя проблема может возникнуть из-за неправильного понимания того, как работает select, но я предположил, что если клиент отключился от сервера, когдаиспользуя select, клиент не будет отображаться в write
.Моя проблема заключается в том, что когда я отключаю тестового клиента от сервера (через shutdown(1)
и close()
) и распечатываю write
, он все равно показывает клиент как подключенный.
[] [<socket.socket fd=7, family=AddressFamily.AF_INET, type=2049, proto=0, laddr=('127.0.0.1', 5000), raddr=('127.0.0.1', 46486)>]
Если я пытаюсь иотправить что-то, что я не вижу, чтобы получить какую-либо ошибку, но при последующей итерации события с сервера, write
изменяется (больше не показывает соединение клиента)
[] [<socket.socket fd=7, family=AddressFamily.AF_INET, type=2049, proto=0, laddr=('127.0.0.1', 5000)>]
и мои ошибки кода на addr = sock.getpeername()
поскольку сокет не имеет аналогов.Я бы подумал, что write
был бы пустым списком, так как сокет не доступен для записи, поэтому я никогда не должен входить в цикл.Почему select возвращает непустой write
?