2013-12-03 3 views
1

У меня есть сервер Tornado WebSocket, работающий в отдельном процессе, запускаемом потоком. Этот поток вызывает метод публикации моего TornadoServer, когда он получает сообщения для отправки через websockets.Список подключенных клиентов в Python Tornado

Запуск Tornado на отдельном процессе был единственным способом, с помощью которого я начал запускать цикл торнадо без блокировки потока при этом вызове.

В моей теме, я начинаю процесс торнадо, вызвав эти методы на нити INIT метод:

self.p = tornado_server.TornadoServer() 
self.p.daemon = True 
self.p.start() 

В этой теме, у меня есть бесконечный цикл, который пытается получить сообщения из очереди, и если он получает сообщения, он называет self.p.publish(client, message).

До сих пор так хорошо.

В процессе торнадо я в основном реализовал систему публикации/подписания. Когда пользователь открывает веб-страницу, страница отправляет сообщение «подписка» для конкретного «клиента». В обратном вызове on_message я добавляю кортеж экземпляра WebSocketHandler и клиента, который пользователь хочет подписаться на глобальный список.

Затем метод публикации должен искать в списке для подписчиков пользователей целевого клиента сообщения и он должен вызывать write_message в WebSocket, хранящемся в этом списке.

Единственное, что не работает, так это то, что мой список «клиентов» имеет разные области или что-то в этом роде.

Это код моего файла tornado_server:

#!/usr/bin/python2 
import tornado.web, tornado.websocket, tornado.ioloop, multiprocessing 

clients = [] 

class TornadoServer(multiprocessing.Process): 

    class WebSocketHandler(tornado.websocket.WebSocketHandler): 
     def on_message(self, message): 
      global clients 
      print 'TORNADO - Received message:', str(message) 
      channel, subtopic = message.split('/') 
      print 'TORNADO - Subscribing:', str(subtopic) 
      clients.append((self, subtopic)) 

     def on_close(self): 
      global clients 
      for websocket, client in clients: 
       if self == websocket: 
        print 'TORNADO - Removed client' 
        to_remove = (self, client) 
        clients.remove(to_remove) 

    def __init__(self): 
     multiprocessing.Process.__init__(self) 
     self.application = tornado.web.Application([(r"/tri-anim", WebSocketHandler)]) 
     self.application.listen(1339) 

    def run(self): 
     tornado.ioloop.IOLoop.current().start() 

    def publish(self, client, message): 
     global clients 
     for websocket, websocketclient in clients: 
      if websocketclient == client: 
       websocket.write_message(str(message)) 

Независимо от того, что я делаю, клиенты не всегда имеют различные области применения. Когда вызывается публикация, «клиенты» всегда пусты. Есть ли способ заставить это работать?

ответ

0

Вы вызываете публикацию в родительском процессе, но список клиентов обновляется только в дочернем процессе. При использовании многопроцессорности каждый процесс получает свою собственную копию всех переменных. Если вы использовали потоки вместо этого, переменные были бы разделены, но даже тогда вам нужно будет использовать IOLoop.instance(). Add_callback для выполнения потоковой передачи обслуживания между потоковым вызовом publish и функцией write_message (которую необходимо вызвать в Поток IOLoop).

Смежные вопросы