Flask-Socketio:命名空间keyerror。,获取已连接客户端的列表

时间:2014-11-13 12:14:46

标签: python sockets flask flask-sockets flask-socketio

我在运行Flask的服务器上使用Flask-Socketio,我的客户端运行javascript。我的所有客户端都使用命名空间'/test'连接到服务器。在客户端上执行某个操作后,我希望客户端在服务器上触发一个遍历所有连接客户端的功能。我使用以下代码段来遍历连接的客户端列表:

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

每个连接都有一个' id'在连接时分配给它的密钥。

但是,有时服务器会给出以下错误,指示找不到命名空间密钥:

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

我不明白为什么我会收到此错误,因为连接到服务器的所有套接字都连接在同一名称空间中。此外,仅在函数调用的一小部分期间才会出现此错误。为什么这个错误不一致?

有没有更好的方法可以迭代连接的客户端列表?

1 个答案:

答案 0 :(得分:3)

您正在迭代包gevent-socketio的私有数据结构,因此可能会发生意外情况。

我不知道这个程序包的内部情况告诉你为什么会发生这种情况,但我认为更安全的方法是建立你自己的连接客户端列表。您可以在连接和断开连接处理程序中向列表中添加和删除客户端。我觉得这样的事情会奏效:

clients = []

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

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