2012-07-27 12 views
17

que tienen una prueba básica Tornado WebSocket:Tornado: identificar/rastrear conexiones de websockets?

import tornado.httpserver 
import tornado.websocket 
import tornado.ioloop 
import tornado.web 

class WSHandler(tornado.websocket.WebSocketHandler): 
    def open(self): 
     print 'new connection' 
     self.write_message("Hello World") 

    def on_message(self, message): 
     print 'message received %s' % message 

    def on_close(self): 
     print 'connection closed' 


application = tornado.web.Application([ 
    (r'/ws', WSHandler), 
]) 


if __name__ == "__main__": 
    http_server = tornado.httpserver.HTTPServer(application) 
    http_server.listen(8888) 
    tornado.ioloop.IOLoop.instance().start() 

Quiero ser capaz de manejar múltiples conexiones (que se parece hacer ya), pero también para poder hacer referencia a otras conexiones. No veo una forma de identificar y realizar un seguimiento de las conexiones individuales, solo para poder manejar los eventos en la conexión abierta, la recepción de mensajes y el cierre de la conexión.

[Editar]
Se pensó en crear un dict donde la clave es la clave Sec-websocket y el valor es el objeto WSHandler ... ¿pensamientos? No estoy seguro de cuán confiable sea Sec-websocket-key para ser único.

+0

Hasta donde yo sé, se creará una única instancia de WSHandler por conexión. Entonces, WSHandlers básicamente son solo interfaces de conexión. ¿Puede ser que desee agregar algún motor de procesamiento de mensajes encima de la red, por ejemplo, como http://code.google.com/p/pyscxml/? – Vladimir

Respuesta

22

El método más simple es sólo para mantener una lista o dict de instancias WSHandler:

class WSHandler(tornado.websocket.WebSocketHandler): 
    clients = [] 

    def open(self): 
     self.clients.append(self) 
     print 'new connection' 
     self.write_message("Hello World") 

    def on_message(self, message): 
     print 'message received %s' % message 

    def on_close(self): 
     self.clients.remove(self) 
     print 'closed connection' 

Si desea identificar las conexiones, por ejemplo por usuario, probablemente tendrá que enviar esa información por el socket.

+0

'Si desea identificar conexiones, p. por usuario, probablemente tendrá que enviar esa información por el socket. No entiendo lo que quieres decir aquí? ¿Cómo identificar una conexión por parte del usuario? – securecurve

+1

Una forma (por ejemplo) sería enviar el ID de sesión sobre el socket, manejarlo en 'on_message', y almacenarlo en la instancia' WSHandler' (o donde sea). –

+0

Ya veo, gracias amigo :)) – securecurve

19

Cole Maclean asnwer es buena como solución simple, cuando solo necesita la lista de todas las conexiones. Sin embargo, si quieres algo más complejo, que se puede controlar fuera de WSHandler ejemplo - ser valiente hacerlo de esta manera:

class WSHandler(tornado.websocket.WebSocketHandler): 

    def open(self): 
     self.id = uuid.uuid4() 
     external_storage[self.id] = {'id':self.id} 
     print 'new connection' 
     self.write_message("Hello World") 

    def on_message(self, message): 
     #Some message parsing here 
     if message.type == 'set_group': 
      external_storage[self.id]['group'] = message.group 
     print 'message received %s' % message 

    def on_close(self): 
     external_storage.remove(self.id) 
     print 'closed connection' 
+0

La respuesta de Cole hace lo que necesito, pero tendré en cuenta la tuya si necesito más control fuera del WSHandler. ¡Aprecia la ayuda! – Joseph

+2

@Nikolay, muy buena respuesta Nikolay, una muy buena idea para realizar un seguimiento de los usuarios sin dejarles enviar quiénes son, puede identificarlos fácilmente y enviar un mensaje/cerrar la conexión en consecuencia ... Buen trabajo :)). Generalmente, el almacenamiento de ese tipo de información se hace con Redis. – securecurve

+0

Definitivamente una forma sólida de manejar este escenario. – kniteli

1

Si los usuarios tienen un token de acceso, esto puede ser anexado a su punto final WebSocket, por ejemplo, y buscó inicializar su socket incluso antes de que se abriera (pero por favor trabaje sobre SSL).

Si un token de acceso no está disponible, ya sea porque el usuario no ha suministrado uno o porque el token que suministra ha caducado, el usuario no está autenticado y matará el socket lo antes posible.

Sin embargo, si hace esto, el token de acceso se debe asociar a un usuario que tendrá un identificador y ese identificador se puede vincular al socket incluso antes de que se haya abierto. El identificador puede servir como una clave de diccionario cuyo valor es un conjunto de sockets vinculados a este usuario.

0

He resuelto este problema al verificar el origen de la conexión. Por lo tanto, anular el método def check_origin(self, origin) puede ayudar. Por ejemplo:

clients = {} 

class WSHandler(tornado.websocket.WebSocketHandler): 


    def check_origin(self, origin): 

     clients[origin] = self 
     print(clients) 
     return True