Skip to content

Closing of connection when client doesn't answer pings #185

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
fschuetz04 opened this issue May 14, 2017 · 2 comments
Closed

Closing of connection when client doesn't answer pings #185

fschuetz04 opened this issue May 14, 2017 · 2 comments

Comments

@fschuetz04
Copy link

I successfully created a python 3.5 websocket server with the following code, but I'm now struggling to close the connection after n missed pings. How is this possible?

import asyncio
import websockets
import threading

def keepalive(conn):
    last_pong = time.time()
    def wrapper():
        pong = conn.ping()
        print('ping sent')
        t = threading.Timer(10, wrapper)
        t.start()
    wrapper()

async def handler(conn, path):
    await conn.send('hello')
    keepalive(conn)
    while True:
        data = await conn.recv()
        print('data: ', data)

start_server = websockets.serve(handler, 'localhost', 5000)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
@aaugustin
Copy link
Member

You shouldn't be using threads. Use an asyncio Task instead. (Besides being correct advice in general — you lose most advantages of asyncio when you mix it with threads — this is also an answer to your question, because communicating with an event loop from another thread causes complications.)

Then, in that task, await asyncio.wait_for(conn.ping(), timeout=10); a timeout exception indicates a timeout.

Create a Future to use as a flag for exiting. When you decide the connection is down, set that Future to some value.

In your main loop, wait for both conn.recv() and that flag in parallel with asyncio.wait. If the flag is set, break from the loop. The handler will then return, which will cause the connection to be closed (uncleanly if the connection is indeed broken).

An easier way to do this is to serialize the two operations instead of parallelizing them. await asyncio.wait_for(conn.recv(), timeout=...); if you get a a timeout, await asyncio.wait_for(conn.ping(), timeout=...); if you get a timeout, assume the connection is broken and exit, else, go back to step 1.

@aaugustin
Copy link
Member

You may be interested in #449.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants