Skip to content
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

How can I send something to a specific websocket in my application from another function? #27

Open
svenstaro opened this issue May 11, 2015 · 7 comments

Comments

@svenstaro
Copy link
Contributor

Imagine this:

@websocket.route("/websocket")
def my_websocket(ws):
    ws.send("foo")

@app.route("/somewhere")
def somewhere():
    #ws.send("bar")

Is this way of working at all possible with websockets? Do I instead need some kind of internal message spooler in my_websocket that I send stuff to which in return sends it to the client? Or can I somehow do this more conveniently as I outlined in my example?

@zeekay
Copy link
Owner

zeekay commented May 11, 2015

If it's a single instance, you can just keep a set of connections. Otherwise you should use redis or something like that for pub/sub.

@svenstaro
Copy link
Contributor Author

Can you post up a snippet? I tried keeping connections in a global list but that didn't work out so well.

@jaapz
Copy link

jaapz commented May 15, 2015

I would personally use redis pub/sub for this. Subscribe to an event (for example "send-to-ws") when the websocket connects. Then publish that event in the "somewhere" route. This way you don't need global lists and it scales great.

You can use Flask-Redis and redis-py for this:
https://github.com/underyx/flask-redis
https://github.com/andymccurdy/redis-py

Use the redis.pubsub() method.

I wouldn't try to keep connection instances in a global, because those won't be shared across instances, if you for example run uWSGI with several workers.

@Necavi
Copy link

Necavi commented May 26, 2015

When I try to do something like:

@app.route("/ready")
def ready():
    ws.send("message")
    return ""

It seems to send nothing through the websocket and instead sends "message" to the browser that requested /ready.

@jaapz
Copy link

jaapz commented May 27, 2015

If you are running one instance of the app (not multiple, like when you use uWSGI), something like this should work:

app = Flask()
websocket = WebSocket(app)
clients = {}

@websocket.route('/connect')
def connect(ws):
    clients[ws.id] = ws

    # keep listening for messages until the connection is closed
    while ws.connected is True:
        message = client.receive()

    # the client is removed when the websocket connection is closed
    del clients[ws.id]

@app.route('/send_all_websockets')
def send_all_websockets():
    """ send a message to all connected websockets """
    for id, client in clients.iteritems()
        client.send('hello')

But again, this will only work when running as one instance.
This is also basically what happens in the chat example: https://github.com/zeekay/flask-uwsgi-websocket/blob/master/examples/chat-gevent/chat.py

@Necavi
Copy link

Necavi commented May 27, 2015

Ahh, that's pretty much exactly what I did, I had figured it was a problem with doing it through uWSGI, that at least gives me somewhere to look, thanks!

@zeekay
Copy link
Owner

zeekay commented Jun 12, 2015

...really should add another example to cover this (extremely common) use case.

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

4 participants