В документации этого нет, хотя есть упоминания. Проблема в том, что PONG он делать умеет, а нужен именно PING.
В принципе, могу расширить вопрос: сокеты делаются мобильников, которые любят отваливаться без уведомлений. Соответственно, обработчики висят и не отваливаются. Их надо пинговать и отстреливать зомбей. Вариант с отстрелом по признаку пользователя не канает, потому параллельные логины — это нормально. Ну и вообще.
Странно. Мне казалось, что там было написано про то, что пинговать клиента надо отдельно. Более того, у меня это установлено. Но или не работает, или я не понимаю, как с этим управляться.
Тогда вопрос: как отлавливать ситуацию, когда клиент мёртв? Как это вообще должно работать? В доках (мне не нравятся эти доки) я этого не нашел и в примерах этого тоже нет. Все примеры, которые попадались, это вообще игнорируют.
776166, да, документация по этому вопросу не содержательна. Но к счастью, легко заглянуть в код. Как это работает, можно посмотреть здесь. А примеры того как применяется, можно найти в тестах.
Сергей Горностаев, к сожалению, из тестов не очень понятно, как это перехватывать и вписать в общую логику приложения.
Вот у меня есть основной обработчик приёма событий из сокета:
async for msg in ws:
if msg.type == aiohttp.WSMsgType.close:
break
elif msg.type == aiohttp.WSMsgType.error:
break
elif msg.type == aiohttp.WSMsgType.text:
# Тут обработка сообщений
pass
#Тут после цикла всё закрывается
Как мне в него встроить функциональность, которая выходит из цикла и мирно всё закрывает, если сокет порвался по heartbeat?
Сергей Горностаев, соединение, видимо, закрывается, но как-то само по себе и этот цикл про это ничего не знает. При корректном закрытии самого сервера лупы ругаются примерно так:
Task was destroyed but it is pending!
task: <Task pending coro=<invites_loop() running at ..../ws/handlers/invites.py:27> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f9773bdec78>()]>>
Task was destroyed but it is pending!
Exception ignored in: <coroutine object invites_loop at 0x7f9773b9a728>
Traceback (most recent call last):
File "..../ws/handlers/invites.py", line 27, in invites_loop
File "/usr/lib/python3.6/asyncio/queues.py", line 169, in get
File "/usr/lib/python3.6/asyncio/base_events.py", line 580, in call_soon
File "/usr/lib/python3.6/asyncio/base_events.py", line 366, in _check_closed
RuntimeError: Event loop is closed
Ругается на последнюю строчку.
Я не понимаю, как это работает. Видимо, надо перехватывать какие-то исключения в лупе в том месте, где происходит ошибка, но я хочу перехвата уровнем выше, чтобы всё по-честному закрывалось. Может, надо async for msg in ws: ещё оборачивать ловца исключения? Там же только сообщения из сокета берутся. Такое ощущение, что он из цикла не выходит вообще, потому что ничего после этого цикла не выполняется.