LINUX.ORG.RU

Django, tornado, redis и websocket'ы

 , , ,


0

1

Всем привет.

Пытаюсь скрестить django + tornado, в видео связки между ними - redis.

Поднимаю tornado-сервер, который слушает определенный порт, к которому и подрубается клиент с помощью websocket'ов.

Из django путем push-сообщений общаюсь с tornado, который слушает определенные сообщения и реагирует на них.

Примерно так (используется библиотека tornado-redis):

from django.conf import settings
from tornado.websocket import WebSocketHandler
import tornado
import json
import tornadoredis

class HardwareTorsockHandler(WebSocketHandler):
    @tornado.gen.engine
    def listen_redis(self):
        self.redis_client = tornadoredis.Client(
            host        = settings.SOCK_REDIS_HOST,
            port        = settings.SOCK_REDIS_PORT,
            password    = settings.SOCK_REDIS_PASSWORD,
            selected_db = settings.SOCK_REDIS_DB
        )

        self.redis_client.connect()

        yield tornado.gen.Task(self.redis_client.subscribe, [
            'pong'
        ])

        self.redis_client.listen(self.on_redis_queue)

    def on_redis_queue(self, message):
        if message.kind == 'message':
            message_body = json.loads(message.body)

            if message.channel == 'pong':
                self.on_pong(message_body)

    def open(self):
        self.storage = HardwareTorsockStorage()
        self.listen_redis()

    def on_pong(self, message):
        self.storage.getConnection(message['code']).write_message(message)

    def on_message(self, message):
        message = json.loads(message)

        if (message['command'] == 'set_code'):
            self.storage.setConnection(message['code'], self)

    def on_close(self):
        print 'Websocket closed'

    def check_origin(self, origin):
        return True

class HardwareTorsockStorage():
    _instance    = None
    _connections = {}

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(HardwareTorsockStorage, cls).__new__(cls, *args, **kwargs)

        return cls._instance

    def setConnection(self, code, socketHandler):
        if code not in self._connections:
            self._connections

 = socketHandler

        return True

    def getConnection(self, code):
        if code not in self._connections:
            return False

        return self._connections

Как можно видеть из кода, каждое соединение складывается в storage, для того, чтобы была возможность отправлять сообщения клиентам выборочно.

Проблема в том, что все «клиенты» подписаны на push-сообщение «pong». Не смотря на то, что вместе с pong'ом приходит код, по которому я идентифицирую клиента, которому отослать данные, происходит это столько раз, сколько есть активных соединений.

Т.е. есть 10 подключенных клиентов, и я даю команду отправить одному из них pong. Pong отправляется только ему, но зато 10 раз.

Может подскажите, как этого избежать?

★★★

Насколько я помню, в стандарте написано, что pong должен отправляться только в ответ на ping. Кроме того, в этих ваших вебсокетах нет такого понятия, как push-сообщение.

anonymous ()
Ответ на: комментарий от anonymous

Вопрос вообще не в том, что я отправляю. Это ради тестирования было сделано. И push-сообщения они не в сокетах, они в redis.

VirRaa ★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.