Skip to content

Instantly share code, notes, and snippets.

@ericremoreynolds
Last active February 25, 2024 21:55
Show Gist options
  • Save ericremoreynolds/dbea9361a97179379f3b to your computer and use it in GitHub Desktop.
Save ericremoreynolds/dbea9361a97179379f3b to your computer and use it in GitHub Desktop.
Flask-socket.io emit to specific clients
<html>
<body>
<h1>I feel lonely</h1>
<script type="text/javascript" src="//code.jquery.com/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.16/socket.io.min.js"></script>
<script type="text/javascript" charset="utf-8">
var socket = io.connect('http://' + document.domain + ':' + location.port);
socket.on('connect', function() {
socket.emit('connected');
});
socket.on('message', function(data) {
$('h1').text(data)
});
</script>
</body>
</html>
from flask import Flask, request
from flask.ext.socketio import SocketIO
app = Flask(__name__, static_folder='')
io = SocketIO(app)
clients = []
@app.route('/')
def index():
return app.send_static_file('client.html')
@io.on('connected')
def connected():
print "%s connected" % (request.namespace.socket.sessid)
clients.append(request.namespace)
@io.on('disconnect')
def disconnect():
print "%s disconnected" % (request.namespace.socket.sessid)
clients.remove(request.namespace)
def hello_to_random_client():
import random
from datetime import datetime
if clients:
k = random.randint(0, len(clients)-1)
print "Saying hello to %s" % (clients[k].socket.sessid)
clients[k].emit('message', "Hello at %s" % (datetime.now()))
if __name__ == '__main__':
import thread, time
thread.start_new_thread(lambda: io.run(app), ())
while True:
time.sleep(1)
hello_to_random_client()
@jeffthemaximum
Copy link

Hey random internet guy here trying to debug issues I'm having with socketio. Why did you put time.sleep(1) on line 36?

@lolobosse
Copy link

@jeffthemaximum I suppose it's to avoid to send one million message per second (because without it'll go as fast as your CPU can handle it ==> Very Quick)

@jakubczaplicki
Copy link

Isn't 'request.namespace' a string or I am missing something ? Not only it doesn't have socket method, but also you can't get a string to emit messages.

@Taiiwo
Copy link

Taiiwo commented Mar 22, 2016

So this is outdated as of flask-socketio 1.0.

The 0.x releases exposed the gevent-socketio connection as request.namespace. In release 1.0 this is not available anymore. The request object defines request.namespace as the name of the namespace being handled, and adds request.sid, defined as the unique session ID for the client connection, and request.event, which contains the event name and arguments.

source: source

I'm still looking into how to do this. The docs mention that a user is automatically added to their own "room" on connection. If I can get the ID of this room, then all I need to do is store that ID somewhere, and emit to it using: (I'm using quotes because my keyboard locale is fucked and I can't type backtick)

emit('foo', 'bar', room=connections[room_id])

This is all I know as of yet. I might remember to update this when I find the answer; If I don't, reply to me and I'll help you if I can.

@Taiiwo
Copy link

Taiiwo commented Mar 22, 2016

Me again. Repo owner states his plans to use the session ID as the room name:

For the upcoming major release of this extension I'm planning to automatically create the individual client rooms. These will be given the name of the session ID, which is exactly what you suggested above.

miguelgrinberg/Flask-SocketIO#89

This has now been implemented. You can access the session ID with

request.sid

short example:

# Object that represents a socket connection
class Socket:
    def __init__(self, sid):
        self.sid = sid
        self.connected = True

    # Emits data to a socket's unique room
    def emit(self, event, data):
        emit(event, data, room=self.sid)

@socketio.on('connect')
def foo():
    sockets[request.sid] = Socket(request.sid)

Now you can just store the sid in a way that represents the reason you want to emit to that socket specifically.

@FreezeSoul
Copy link

nice work

@ramizdemiurge
Copy link

ramizdemiurge commented Sep 12, 2017

Guys, can't resolve

Unresolved attribute reference 'sid' for class 'Request'

Tryng to get request.sid
Found nothing helpful here

@herbherbherb
Copy link

so say if a client want to change from room A to room B, how does it work? Does he have to leave a room first and join another room? if there something called change_room?

@Taiiwo
Copy link

Taiiwo commented Apr 9, 2018

Dude, literally having problems with this same thing 2 years later, find this gist as the first result on google for "flask socketio send to specific client", and scroll down to see my own account giving the solution. I totally forgot!

That being said, it is worth noting that the socket id of a socket under a namespace is now formatted "/endpoint#id", and this room method requires you to parse the id out of that as far as I'm aware.

@saurabhrb
Copy link

server_variables = {}

# route for socket connection
@SOCKETIO.on('connect', namespace='/test')
def test_connect():
    if request.sid not in server_variables.keys():
        server_variables[request.sid] = {'sid' : request.sid, 'stats' : 'connected'}
    print(str(request.sid) + '=> Client Connected '
    # to broadcaset to all but self
    for k in server_variables.keys():
    	if k!= requst.sid:
    		emit('my response', {'data': 'This sid ' + str(request.sid) + ' just connected', 'stats' : 'RUNNING'}, room = k)
    # to send only to first socket that was connected to this server
    emit('my response', {'data': 'This sid ' + str(request.sid) + ' just connected','stats' : 'RUNNING'}, room = server_variables[server_variables.keys()[0]]['sid'])

# route for socket disconnection
@SOCKETIO.on('disconnect', namespace='/test')
def test_disconnect():
    if request.sid in server_variables.keys():
        server_variables[request.sid]['stats'] = 'disconnected'
    print(str(request.sid) + '=> Client Disconnected '

works in my project https://github.com/saurabhrb/LIVE_TERMINAL_FLASK

@hktime9
Copy link

hktime9 commented Feb 21, 2019

I can't seem to get around this. "request.namespace" gives me a '/'. I tried to emit using the room argument by passing in the "request.sid" but that causes the emit to not work at all. Can anyone tell what I'm doing wrong?

@kanmeugne
Copy link

Isn't 'request.namespace' a string or I am missing something ? Not only it doesn't have socket method, but also you can't get a string to emit messages.

I am stucked on that too. Can't figure what version to use in order to get the right API.

@juniordnts
Copy link

juniordnts commented Aug 18, 2019

I tried this and works for me:

io.emit('message', "Hello at %s" % (datetime.now()), room=clients[k])

This clients[k] is the ID of the conection... On cliente is socket.id and in the server is request.sid (This one you need to import from flask import request)

I dont tried if puttin an array in room will send to all clients in there...

@franklincm
Copy link

@juniordnts worked perfectly, thanks!

@davidmroth
Copy link

room=self.sid

Me again. Repo owner states his plans to use the session ID as the room name:

For the upcoming major release of this extension I'm planning to automatically create the individual client rooms. These will be given the name of the session ID, which is exactly what you suggested above.

miguelgrinberg/Flask-SocketIO#89

This has now been implemented. You can access the session ID with

request.sid

short example:

# Object that represents a socket connection
class Socket:
    def __init__(self, sid):
        self.sid = sid
        self.connected = True

    # Emits data to a socket's unique room
    def emit(self, event, data):
        emit(event, data, room=self.sid)

@socketio.on('connect')
def foo():
    sockets[request.sid] = Socket(request.sid)

Now you can just store the sid in a way that represents the reason you want to emit to that socket specifically.

Great response! Short and concise! Thanks for the example.

@charles-dr
Copy link

I tried this and works for me:

io.emit('message', "Hello at %s" % (datetime.now()), room=clients[k])

This clients[k] is the ID of the conection... On cliente is socket.id and in the server is request.sid (This one you need to import from flask import request)

I dont tried if puttin an array in room will send to all clients in there...

Thanks, @juniordnts.
The above code worked for me finally, and here is my code.
Hope it helps others save time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment