27

I see there is a question about this topic, but the specific code is not outlined. Say I want to emit only to the first client.

For example (in events.py):

clients = []

@socketio.on('joined', namespace='/chat')
def joined(message):
    """Sent by clients when they enter a room.
    A status message is broadcast to all people in the room."""
    #Add client to client list
    clients.append([session.get('name'), request.namespace])
    room = session.get('room')
    join_room(room)
    emit('status', {'msg': session.get('name') + ' has entered the room.'}, room=room)
    #I want to do something like this, emit message to the first client
    clients[0].emit('status', {'msg': session.get('name') + ' has entered the room.'}, room=room)

How is this done properly?

Thanks

shell
  • 1,867
  • 4
  • 23
  • 39

1 Answers1

33

I'm not sure I understand the logic behind emitting to the first client, but anyway, this is how to do it:

clients = []

@socketio.on('joined', namespace='/chat')
def joined(message):
    """Sent by clients when they enter a room.
    A status message is broadcast to all people in the room."""
    # Add client to client list
    clients.append(request.sid)

    room = session.get('room')
    join_room(room)

    # emit to the first client that joined the room
    emit('status', {'msg': session.get('name') + ' has entered the room.'}, room=clients[0])

As you can see, each client has a room for itself. The name of that room is the Socket.IO session id, which you can get as request.sid when you are handling an event from that client. So all you need to do is store this sid value for all your clients, and then use the desired one as room name in the emit call.

Miguel Grinberg
  • 65,299
  • 14
  • 133
  • 152
  • Hey, thanks for the fast reply! Yeah I would not actually do this I was just trying to create an example where you would emit to a specific client. Thanks Miguel again, very appreciated! – shell Sep 11 '16 at 00:35
  • If I use a DB, I could make a new column, f.e. user_room and save there a unique string, which can identify that user for private chat? – Roman Apr 25 '18 at 07:00
  • I asked this in an other comment, but using the unique user id is stupid, because someone could easily guess it and join the private conversation, right? – Roman Apr 25 '18 at 07:02
  • @Roman no. The unique IDs are not secret. All communications pass through the server anyway. If client A wants to send a message to client B, two things need to happen. A emits a message to the server, asking it to deliver a message to B. Then the server emits the message to B. Standard authentication mechanisms can be used to ensure that clients are who they say they are. – Miguel Grinberg Apr 26 '18 at 03:31
  • @Miguel okay thank you very much. So creating a new column was not needed as I could use the normal user ID. – Roman Apr 26 '18 at 06:32
  • @Miguel Can you please check this [question](https://stackoverflow.com/questions/50059102/python-heroku-configure-procfile-gunicorn-gevent-for-socket-io-chat-app-runt), the last two edits? I have deployed the chat app on heroku and it seems to work now, but I still see a huge error, my guess it that only one connection works right now. I would be really thankful if you find the time. – Roman Apr 27 '18 at 09:54
  • Is `clients[0]` same as `session.get('room')` in this sample? Shouldn't we do `join_room(request.sid)`? – Phani Rithvij May 15 '20 at 07:34
  • 2
    @Miguel Is creating a separate room for all clients the only way to emit to a particular client? I have a long task that needs to be finished at the server/backend. Instead of polling, I used a celery flask application and once the job is finished I wish to emit the result to the particular who initiated the request. – Naman Mar 13 '21 at 05:35
  • 1
    Each client is allocated a room automatically when it connects. Use the `sid` as the name of the room. – Miguel Grinberg Mar 13 '21 at 16:01
  • @MiguelGrinberg Using a real time web application as a human-machine interface (HMI) to control a physical process on the backend is an instance when the first client may need special treatment. For example, camera footage is viewed by several logged-in clients, all of which have the ability to view footage and control the pan & tilt of the camera. However, to prevent all the clients from unknowingly fighting over where the camera points, only the first client to click a "take control" button will be presented with movement controls. – jacob Dec 21 '22 at 17:46
  • Flask-SocketIO does not provide any features that can help with this, but your application is free to consider any of the connected clients as special and handle them differently than the rest. – Miguel Grinberg Dec 21 '22 at 18:28