Можно ли отправить сообщение всем активным соединениям WebSocket? Использование веб-сокетов node.js или python tornado

Я экспериментирую с созданием приложения на основе веб-сокета.

Мне интересно, можно ли отправить сообщение всем активным соединениям, поскольку они являются постоянными.

Скажем, у меня есть сайт с живым аукционом, и у меня есть несколько пользователей, просматривающих страницу аукциона, каждый из которых подключен через сокеты к моему серверу. Теперь предположим, что один пользователь повышает ставку. Я хочу отправить сообщение всем подключенным клиентам. Самый простой способ - заставить клиентов опрашивать сервер через сокет каждую секунду, но я думаю, что идея веб-сокетов состоит в том, чтобы иметь настоящую двунаправленную связь.

Как это может быть сделано?

заранее спасибо,

Ротем


person Rotem Tamir    schedule 08.07.2011    source источник
comment
У меня тоже именно этот вопрос. Может ли кто-нибудь сказать, как я могу сделать это в сервлете, используя сервер tomcat. Я создал WebSocketServlet, следуя этому примеру. - gist.github.com/chitan/3063774   -  person Sourav301    schedule 25.09.2013


Ответы (3)


Решение socket.io:

// note, io.listen() will create a http server for you
var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  io.sockets.emit('this', { will: 'be received by everyone' });

  socket.on('private message', function (msg) {
    console.log('I received a private message from ', socket.id, ' saying ', msg);
    // Echo private message only to the client who sent it
    socket.emit('private message', msg);
  });

  socket.on('disconnect', function () {
    // This will be received by all connected clients
    io.sockets.emit('user disconnected');
  });
});

all_active_connections = {};

webocket server (есть many), сделайте то же самое вручную:

  var ws = require("ws");

  global_counter = 0;
  all_active_connections = {};

  ws.createServer(function (websocket) 
  {
      websocket.on('connect', function() 
      {
          var id = global_counter++;
          all_active_connections[id] = websocket;
          websocket.id = id; 
      }).on('data', function (data) {
          if (data == 'broadcast me!')
          {
              for (conn in all_active_connections)
                 all_active_connections[conn].write(data);
          }       
      }
    }).on('close', function() {
        delete all_active_connections[websocket.id];
    });
  }).listen(8080);
person Andrey Sidorov    schedule 08.07.2011
comment
Не могли бы вы объяснить, как это сделать в сервлете. - person Sourav301; 25.09.2013
comment
что вы называете сервлетом? - person Andrey Sidorov; 25.09.2013

Для решения, основанного на торнадо/торнадио, ваш класс SocketConnection должен поддерживать список соединений на уровне класса. Ваш обработчик on_connect добавит соединение в этот список, а on_close удалит его. Пример псевдокода см. в этой публикации Сержа С. Коваль. Код воспроизводится ниже:

Объявите свой класс подключения TornadIO:

class MyConnection(SocketConnection):
    participants = set()

    @classmethod
    def broadcast(cls, msg):
        for p in cls.participants:
            p.send(msg)

    @classmethod
    def controller_msg(cls, msg):
        cls.broadcast(msg)

В ветке опроса вашего устройства сделайте что-то вроде:

while True: 
    datum = file.readline() 
    if len(datum) > 2: 
        t = json.loads(datum) 
        ...
        def callback():
            MyConnection.controller_msg(t)

        io_loop.add_callback(callback)

Кроме того, gevent-socketio поддерживает широковещательную рассылку сообщений, но она основана на gevent, а не на торнадо.

ОБНОВИТЬ:

tornadio2 уже поддерживает список активных сеансов, поэтому все, что вам нужно сделать, это:

class MyConnection(SocketConnection):
    def broadcast(self, event, message):
        for session_id, session in self.session.server._sessions._items.iteritems():
            session.conn.emit(event, message)

Это работает, потому что каждый экземпляр соединения имеет ссылку на свой сеанс, который имеет ссылку на глобальный маршрутизатор, используемый для создания приложения (хранящегося как server), который поддерживает список сеансов в объекте SessionContainer в _sessions. Теперь всякий раз, когда вы хотите передать сообщение в своем классе подключения, просто выполните:

self.broadcast('my_custom_event', 'my_event_args')
person Tony Abou-Assaleh    schedule 08.03.2012

Этот пример redis + websockets (на торнадо) должен вам помочь. По сути, у вас есть список слушателей, которые должны быть уведомлены, и как только сообщение будет получено, выполните итерацию по этому списку и проинформируйте их.

person calvinkrishy    schedule 28.07.2011
comment
Обновился на другой - person calvinkrishy; 01.05.2015