2012-07-27 20 views
17

Mam podstawowy test Tornado websocket:Tornado: Identyfikacja/śledzenie połączeń stron internetowych?

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() 

Chcę być w stanie obsługiwać wiele połączeń (które wydaje się, że już zrobić), ale także, aby móc odwoływać się inne połączenia. Nie widzę sposobu, aby zidentyfikować i śledzić poszczególne połączenia, aby móc obsługiwać zdarzenia podczas otwierania połączenia, odbierania wiadomości i zamykania połączenia.

[Edytuj] Myśl o stworzeniu dyktatury, w której kluczem jest klucz Sec-websocket, a wartością jest obiekt WSHandler ... myśli? Nie jestem pewien, jak niezawodny Sec-websocket-key ma być unikalny.

+0

Z tego co wiem, zostanie utworzona pojedyncza instancja WSHandler na połączenie. Tak więc WSHandlers to w zasadzie tylko interfejsy połączeń. Może chcesz dodać silnik przetwarzania komunikatów na szczycie sieci, na przykład http://code.google.com/p/pyscxml/? – Vladimir

Odpowiedz

22

Najprostszym sposobem jest po prostu zachować listę lub dict instancji 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' 

Jeśli chcesz zidentyfikować połączenia, na przykład przez użytkownika, prawdopodobnie będziesz musiał wysłać te informacje przez gniazdo.

+0

'Jeśli chcesz zidentyfikować połączenia, np. przez użytkownika, prawdopodobnie będziesz musiał wysłać te informacje przez gniazdo. " Nie rozumiem, co masz na myśli? Jak zidentyfikować połączenie przez użytkownika? – securecurve

+1

Jednym ze sposobów (na przykład) byłoby wysłanie identyfikatora sesji przez gniazdo, obsłużenie go w 'on_message' i zapisanie go w instancji' WSHandler' (lub gdziekolwiek). –

+0

Rozumiem, dziękuję koleś :)) – securecurve

19

Cole Maclean asnwer jest dobrym rozwiązaniem, gdy potrzebujesz tylko listy wszystkich połączeń. Jednakże, jeśli chcesz coś bardziej złożonego, które mogą być monitorowane poza WSHandler przykład - być odważny zrobić to tak:

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

Odpowiedź Cole'a robi to, czego potrzebuję, ale zachowam twoje zdanie, jeśli potrzebuję większej kontroli poza samym WSHandler. Doceń pomoc! – Joseph

+2

@Nikolay, bardzo dobra odpowiedź Nikolay, bardzo fajny pomysł, aby śledzić użytkowników, nie pozwalając im wysyłać wiadomości, kim są, możesz łatwo je zidentyfikować i wysłać wiadomość/odpowiednio zamknąć połączenie ... Dobra robota :)). Zazwyczaj przechowywanie tego rodzaju informacji odbywa się za pomocą Redis. – securecurve

+0

Zdecydowanie solidny sposób radzenia sobie z tym scenariuszem. – kniteli

1

Jeśli użytkownicy mają token dostępu, może to być dołączone do końcowego websocket, powiedzmy i pobrane podczas inicjalizacji twojego gniazda, zanim jeszcze zostanie otwarte (ale pracuj nad SSL).

Jeśli token dostępu jest niedostępny, ponieważ użytkownik nie podał jednego lub dostarczony przez niego token wygasł, użytkownik nie jest uwierzytelniony, a ty najszybciej zabijesz gniazdo.

Jednak w tym przypadku token dostępu powinien być powiązany z użytkownikiem, który będzie miał identyfikator, a następnie ten identyfikator będzie można powiązać z gniazdem jeszcze przed jego otwarciem. Identyfikator może służyć jako klucz słownika, którego wartością jest zestaw gniazd powiązanych z tym użytkownikiem.

0

Rozwiązałem ten problem, sprawdzając pochodzenie koneksji. Zastanowienie metody def check_origin(self, origin) może pomóc. Na przykład:

clients = {} 

class WSHandler(tornado.websocket.WebSocketHandler): 


    def check_origin(self, origin): 

     clients[origin] = self 
     print(clients) 
     return True 
Powiązane problemy