24

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,797
  • 3
  • 19
  • 35

1 Answers1

27

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
  • 61,236
  • 14
  • 124
  • 145
  • 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
  • 1
    @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