gmqtt
gmqtt copied to clipboard
Unhandled [WinError 10054]
Елена, извините, опишу на русском, ибо писать много, а мой английский совсем не вери-велл :(
Пришлось протестировать на богопротивной Windows и сразу столкнулся с проблемой. Вкратце: обычное поведение клиента состоит в том, что при неудачном подключении к брокеру, выполняются попытки переподключения.
Я категорически несогласен с этим поведением и не совсем понимаю, как это поведение обойти.
Пытаюсь обойти следующим образом:
try:
await self._client.connect(self._host, self._port, self._ssl, version=MQTTv311)
except:
self._client.stop_reconnect()
await self._client.disconnect()
И это даже работает - при неудачной попытке первичного подключения, клиент бросает дальнейшие попытки.
Но не на Windows...
В начале теста я забыл изменить значение параметра ssl метода connect - брокер требует безопасное подключение, но я передал значение False. В итоге наблюдаю следующую картину:
[CONNECTION MADE]
[EXC: CONN LOST]
================================================================================
Traceback (most recent call last):
File "...Python\lib\asyncio\selector_events.py", line 804, in _read_ready__data_received
data = self._sock.recv(self.max_size)
ConnectionResetError: [WinError 10054] Удаленный хост принудительно разорвал существующее подключение
================================================================================
[CMD 0xe0] b''
[TRYING WRITE TO CLOSED SOCKET]
И так по кругу. Приведенный выше код try...except, который призван остановить попытки после первой же неудачной, в данном случае не срабатывает.
Посоветуйте, что можно сделать?
Вопрос, на самом деле, даже более широкий: каким образом я могу не дожидаться подключения к брокеру, если уже после первой попытки понятно, что продолжать бесполезно - ошибочные host и порт, некорректные логин и пароль и т.п.? В то же время, если возникла необходимость переподключения в процессе работы (например, на какое-то время пропало соединение), то продолжать попытки нужно практически до победы.
@Allineer Попробуйте сделать self._client.stop_reconnect() еще до собственно await self._client.connect. Эта функция просто изначально поменяет конфиг количества неудачных переподключений.
@Lenka42 логично :) А как потом включить реконнект, после успешного первичного подключения на случай последующих проблем с подключением?
И остается проблема с WinError - при возникновении такой ошибки, управление не возвращается из метода connect - получается такой себе вечный await.
Обидно конечно, что на винде не работает. У нас на Линуксе как раз такое поведение как вы описываете, при первом коннэкте если не подключилось - ошибка. А если первый раз успешно подключилось - дальше реконнэкты при разрывах.
Мне кажется эту ошибку будет сложно отловить, у нее вон трэйсбэк напрямую из asyncio а не вашего кода. Но я завтра ее еще поковыряю.
А вернуть реконнэкты можно методом client.set_config({'reconnect_retries': 10, 'reconnect_delay': 60})
reconnect_retries - количество допустимых неудачных подключений подряд
reconnect_delay - ожидание в секундах между попытками подключения
А какой у вас брокер?
mosquitto 1.5.7-1
при первом коннэкте если не подключилось - ошибка. А если первый раз успешно подключилось - дальше реконнэкты при разрывах.
Тоже не совсем так, правда на macOS:
Using selector: KqueueSelector
[CONNECTION MADE]
[CMD 0x20] b'\x00\x05'
[CONNACK] 0x5
[QoS query IS EMPTY]
[RECV EMPTY] Connection will be reset automatically.
[CONN CLOSE NORMALLY]
[CMD 0xe0] b''
[CONNECTION MADE]
[CMD 0x20] b'\x00\x05'
[CONNACK] 0x5
[QoS query IS EMPTY]
[RECV EMPTY] Connection will be reset automatically.
[CONN CLOSE NORMALLY]
[CMD 0xe0] b''
Или некорректные имя пользователя-пароль считаются успешным подключением?