簡體   English   中英

Ruby - 將消息發送到Websocket

[英]Ruby - Send message to a Websocket

如何在后台進程中使用Ruby將數據發送到WebSocket?

背景

我已經有一個使用websocket-eventmachine-server gem運行Websocket服務器的單獨ruby文件。 但是,在我的Rails應用程序中,我想在后台任務中將數據發送到websocket。

這是我的WebSocket服務器:

EM.run do
  trap('TERM') { stop }
  trap('INT') { stop }

  WebSocket::EventMachine::Server.start(host: options[:host], port: options[:port]) do |ws|

    ws.onopen do
      puts 'Client connected'
    end

    ws.onmessage do |msg, type|
      ws.send msg, type: type
    end

    ws.onclose do
      puts 'Client disconnected'
    end

  end

  def stop
    puts 'Terminating WebSocket Server'
    EventMachine.stop
  end
end

但是,在我的后台進程中(我使用的是Sidekiq),我不確定如何連接到WebSocket並向其發送數據。

這是我的Sidekiq工作人員:

class MyWorker
  include Sidekiq::Worker

  def perform(command)
    100.times do |i|
      # Send 'I am on #{i}' to the Websocket
    end  
  end

end

我希望能夠做一些像EventMachine::WebSocket.send 'My message!' 但我沒有看到API或類似的東西。 在Ruby中將數據發送到WebSocket的正確方法是什么?

一般承認的答案

你保留當前的websocket服務器:

您可以將Iodine用作一個簡單的websocket客戶端進行測試。 它使用自己的基於reactor模式的代碼運行后台任務,並有一個websocket客戶端(我有偏見,我是作者)。

你可以這樣做:

require 'iodine/http'
Iodine.protocol = :timers
# force Iodine to start immediately
Iodine.force_start!

options = {}
options[:on_message] = Proc.new {|data| puts data}

100.times do |i|
    options[:on_open] = Proc.new {write "I am number #{i}"}
    Iodine.run do
        Iodine::Http.ws_connect('ws://localhost:3000', options) 
    end
end

PS

我建議為你的websockets使用一個框架,比如Plezi (我是作者)。 一些框架允許你在Rails / Sinatra應用程序中運行他們的代碼(Plezi這樣做,我認為Faye雖然不是嚴格意義上的框架,但也是如此)。

直接使用EM是非常核心的,在處理Websockets時需要管理很多東西,一個好的框架可以幫助您管理。

編輯3

從Iodine 0.7.17開始支持(重新)支持Iodine WebSocket客戶端連接,包括OpenSSL >= 1.1.0時的TLS連接。

以下代碼是原始答案的更新版本:

require 'iodine'

class MyClient
  def on_open connection
    connection.subscribe :updates
    puts "Connected"
  end
  def on_message connection, data
    puts data
  end
  def on_close connection
    # auto-reconnect after 250ms.
    puts "Connection lost, re-connecting in 250ms"
    Iodine.run_after(250) { MyClient.connect }
  end

  def self.connect
    Iodine.connect(url: "ws://localhost:3000/path", handler: MyClient.new)
  end
end


Iodine.threads = 1
Iodine.defer { MyClient.connect if Iodine.master? }
Thread.new { Iodine.start }

100.times {|i| Iodine.publish :updates, "I am number #{i}" }

編輯2

這個答案現在已經過時了,因為Iodine 0.2.x不再包括客戶了。 對於websocket客戶端使用碘0.1.x或不同的gem

websocket-eventmachine-server是一個websockets 服務器

如果你想使用ruby連接到websocket服務器,你可以用一些寶石來做,比如

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM