aio-libs / aiohttp

Asynchronous HTTP client/server framework for asyncio and Python
https://docs.aiohttp.org
Other
14.79k stars 1.97k forks source link

Can't detect disconnection on wifi websocket client #2368

Open deunix-educ opened 6 years ago

deunix-educ commented 6 years ago

Long story short

I use several esp8266 (a wifi IOT) as websocket client with aiohttp 2.3.1 websocket server . Works perfectly but i can't detect disconnection.

Expected behaviour

I want to detect disconnection when an esp8266 disappear.

Actual behaviour

I detect connections and play with all clients ESP8266. The method detecst all disconnections at heartbeat delay but do nothing. I there any solution?

Steps to reproduce

A background loop to send a ping to all client esp8266. WebSocketResponse instance with heartbeat param set.

Your environment

Debian machine + Python 3.5 + aiohttp v 2.3.1

fafhrd91 commented 6 years ago

this seems like a bug.

deunix-educ commented 6 years ago

Probably by sending a message from WebSocketResponse._pong_not_received (after test) to WebSocketResponse.receive loop. I don't know to do how to do.

deunix-educ commented 6 years ago

I do not know if it's a good solution, but here is the code that allows me to detect the disconnection of all esp8266. :

import asyncio
from aiohttp import web

class WebSocketResponse(web.WebSocketResponse):
    def _pong_not_received(self):
        if self._req is not None and self._req.transport is not None:
            self._req.app.sockets.remove_ws(self) #  code that do the job

            self._closed = True
            self._close_code = 1006
            self._exception = asyncio.TimeoutError()
            self._req.transport.close()
junqed commented 6 years ago

Have you tried like in close method https://github.com/aio-libs/aiohttp/blob/5de1c0b1ad7107502215e7b3a4980159eb812552/aiohttp/client_ws.py#L132 ?

I have the same thing — the pong callback doesn't stop reading loop :(

junqed commented 6 years ago

BTW it happens not in a wifi network

anatoly-kussul commented 6 years ago

Had same problem on wired network, adding receive_timeout to ws_connect solved this problem for me. But i think this works only if you have infinite receiving loop (you will get asyncio.TimeoutError on await ws.receive()) async with session.ws_connect(url, proxy=proxy_url, heartbeat=1, receive_timeout=5) as ws: