Сервер веб-сокета машины событий: как отправлять периодические сообщения клиенту?

Я хотел бы использовать рубиновый язык gem em-websocket: https://github.com/igrigorik/em-websocket для запуска сервера веб-сокетов над машиной событий.

Я успешно запускаю демонстрацию эхо-сервера:

EM.run {
  EM::WebSocket.run(:host => "0.0.0.0", :port => 8080) do |ws|
    ws.onopen { |handshake|
      puts "WebSocket connection open"

      ws.send "Hello Client, you connected to #{handshake.path}"
    }

    ws.onclose { puts "Connection closed" }

    ws.onmessage { |msg|
      puts "Recieved message: #{msg}"
      ws.send "Pong: #{msg}"
    }
  end
}

теперь я хотел бы разработать демонстрацию, в которой сервер мог бы передавать каждые n мс (случайное значение) некоторые данные через сообщение веб-сокета подключенному клиенту... практически что-то вроде:

def periodic_push
    # random elapsed: from 100 milliseconds to 6 seconds
    msec_value =  (rand(100..6000) / 1000.0 )
    message = "time: #{Time.now} value: #{msec_value.to_s}"

    ws.send message
    puts message

    sleep (msec_value)
end

Я знаю, что НЕ могу использовать системный вызов sleep() внутри цикла EM, но я не могу понять, как вставить периодическое событие в EM::WebSocket loop; может с EventMachine::PeriodicTimer ? как ?

Кто-нибудь может помочь мне с примером кода? Благодарность! Джорджио


person Giorgio Robino    schedule 22.08.2013    source источник


Ответы (2)


Я сам нашел решение: в приведенном ниже коде сервер отправляет сообщение веб-сокета клиенту каждые 500 мс. ( PeriodicTimer.new (0.5) ).

Сейчас у меня возникла проблема: как динамически сбросить таймер, чтобы он отправлял сообщение каждые N мсек, где N — случайное значение... Есть идеи?

require 'eventmachine'
require 'em-websocket'
require 'socket'

EM.run {
  EM::WebSocket.run(:host => "0.0.0.0", :port => 8080) do |ws|

    ws.onopen { |handshake|
      puts "WebSocket connection open"
      ws.send "Hello Client, you connected to: #{Socket.gethostname}. websocket server path: #{handshake.path}"


    timer = EventMachine::PeriodicTimer.new(0.5) do

      value =  (rand(100..6000) / 1000.0 )
      message = "time: #{Time.now} value: #{value.to_s}"

      ws.send message
      puts message

    end
    }

    ws.onclose { puts "Connection closed" }

    #ws.onmessage { |msg|
    #  puts "Received message: #{msg}"
    #  ws.send "Pong: #{msg}"
    #}
  end
}
person Giorgio Robino    schedule 22.08.2013

Моя логика заключалась бы в том, чтобы запустить машину событий на минимально возможную продолжительность и добавить задержку для случайного значения, которое вам нужно. Например

'ws.onopen { |handshake|
  puts "WebSocket connection open"
  ws.send "Hello Client, you connected to: #{Socket.gethostname}. websocket server path: #{handshake.path}"


timer = EventMachine::PeriodicTimer.new(0.0) do #the delay is kept to minimum here

  value =  (rand(100..6000) / 1000.0 )
  message = "time: #{Time.now} value: #{value.to_s}"

  ws.send message
  puts message
 delay(2) #2 seconds delay or the dynamic delay you want
end
}`

Контекст: Сам пробовал

person WingCode    schedule 12.07.2016
comment
Было бы полезно предоставить контекст для вашего ответа - person mhatch; 12.07.2016