Python Asyncio Websocket not detecting a disconnec

2019-05-23 05:25发布

问题:

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

this is my websocket handler it uses aiohttp on top of asyncio. The problem is if i disconnect the clients wifi connection its not detecting that the connection is lost. i also tried using the Websockets module, but the same thing happend. But when the client is on localhost then working perfectly. Whats the main reason for this, and if anyone could explain how to properly catch network exceptions inside asyncio.

回答1:

TLDR; ping your server by client.

That's how TCP stack works: graceful disconnection requires sending a packet to peer. If the network is broken not data transfer is available.

Localhost network has all the knowledge about disconnections but real network misses the info about all moving parts.

The only reliable way to detect disconnection is waiting for a message from peer (it can be ping message or regular data packet) with a timeout.

If timeout is expired -- the peer is gone, the local end of communication channel should be closed as well.

That's why any long-living communication over TCP is a little more complex than it seems -- all production-level systems use pings and timeouts internally. It affects not only websockets but any messengers with custom protocol.