Python Asyncio Websocket не обнаруживает отключение по Wi-Fi, но делает это на локальном хосте - PullRequest
0 голосов
/ 28 апреля 2018
async def relayHandler(request):
print('Websocket connection starting')
ws = aiohttp.web.WebSocketResponse(autoclose=True)
await ws.prepare(request)
print('Websocket connection ready')

async for msg in ws:
    print(msg)
    if msg.type == aiohttp.WSMsgType.TEXT:
        print(msg.data)
        if msg.data == 'close':
            await ws.close()
        else:
            await ws.send_str(msg.data + '/answer')
    elif msg.type == aiohttp.WSMsgType.ERROR:
        print('ws connection closed with exception %s' %ws.exception())
print('Websocket connection closed')
return ws

это мой обработчик веб-сокетов, он использует aiohttp поверх asyncio. Проблема в том, что если я отключаю Wi-Fi-соединение с клиентами, оно не обнаруживает, что соединение потеряно. Я также попытался использовать модуль Websockets, но то же самое произошло. Но когда клиент на localhost, то работает отлично. Какова основная причина этого, и если кто-нибудь может объяснить, как правильно перехватывать исключения из сети внутри asyncio.

1 Ответ

0 голосов
/ 28 апреля 2018

TLDR; пинг вашего сервера клиентом.

Вот как работает стек TCP: для корректного отключения требуется отправка пакета равноправному узлу. Если сеть не работает, передача данных невозможна.

Сеть Localhost обладает всеми знаниями об отключениях, но в реальной сети отсутствует информация обо всех движущихся частях.

Единственный надежный способ обнаружения отключения - это ожидание сообщения от однорангового узла (это может быть сообщение ping или обычный пакет данных) с тайм-аутом.

Если время ожидания истекло - одноранговый узел пропал, локальный конец канала связи также должен быть закрыт.

Вот почему любое долгоживущее общение по TCP немного сложнее, чем кажется - все системы производственного уровня используют пинг и тайм-ауты внутри. Это касается не только веб-сокетов, но и любых мессенджеров с пользовательским протоколом.

...