Flask-Socketio: namespace keyerror., get list of connected clients

3.3k views Asked by At

I am using Flask-Socketio on my server that is running Flask and my clients run javascript. All my clients connect to the server using the namespace '/test'. Upon a certain action on the client, I want the client to trigger a function on the server that iterates through all the connected clients. I am using the following code segment to iterate through the list of connected clients:

for sessid, socket in request.namespace.socket.server.sockets.items():
    print "socket id : %r" % (socket['/test'].session['id'])

where each connection has an 'id' key assigned to it on connection.

However sometimes the server gives the following error indicating that the namespace key was not found:

Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/gevent/greenlet.py", line 327, in run
  result = self._run(*self.args, **self.kwargs)
File "/usr/local/lib/python2.7/dist-packages/socketio/virtsocket.py", line 403, in_receiver_loop
  retval = pkt_ns.process_packet(pkt)
File "/usr/local/lib/python2.7/dist-packages/socketio/namespace.py", line 155, in process_packet
  return self.process_event(packet)
File "/usr/local/lib/python2.7/dist-packages/flask_socketio/__init__.py", line 64, in process_event
  return self.socketio._dispatch_message(app, self, message, args)
File "/usr/local/lib/python2.7/dist-packages/flask_socketio/__init__.py", line 137, in _dispatch_message
  ret = self.messages[namespace.ns_name][message](*args)
File "/home/ubuntu/flask-app/current/py/flaskapp/main/sockets.py", line 190, in gameInitialisedByClient
  print "id : %r  random: %r" % (socket['/test'].session['id'], socket['/test'].session['random'])
File "/usr/local/lib/python2.7/dist-packages/socketio/virtsocket.py", line 190, in __getitem__
  return self.active_ns[key]
KeyError: '/test'
<Greenlet at 0x7f483bc6bf50: <bound method Socket._receiver_loop of <socketio.virtsocket.Socket object at 0x7f483a5ac6d0>>> failed with KeyError

I do not understand why i get this error since all my sockets that connect to the server are connecting on the same namespace. Moreover, this error is experienced only during a fraction of the function calls. Why isn't this error consistent?

Is there a better way in which I could iterate through the list of connected clients?

1

There are 1 answers

2
Miguel Grinberg On BEST ANSWER

You are iterating over a private data structure of package gevent-socketio, so unexpected things can happen.

I do not know the internals of this package to tell you why this happens, but I think a much safer approach would be for you to build your own list of connected clients. You can add and remove clients to your list in the connect and disconnect handlers. I think something like this will work:

clients = []

@socketio.on('connect', namespace='/test')
def connect():
    clients.append(request.namespace)

@socketio.on('disconnect', namespace='/test')
def disconnect():
    clients.remove(request.namespace)