如何在 ruby​​ on rails 中通过 websocket 发送保持活动的数据包

Posted

技术标签:

【中文标题】如何在 ruby​​ on rails 中通过 websocket 发送保持活动的数据包【英文标题】:How to send a keep-alive packet through websocket in ruby on rails 【发布时间】:2015-10-27 11:09:14 【问题描述】:

我想发一个

“从客户端保持活动状态”

我的 websocket 连接每 30 秒发送一次消息。这是我在 websocket 初始化程序中的代码:

ws = WebSocket::Client::Simple.connect 'wss://bitcoin.toshi.io/'

ws.on :message do |msg|
  rawJson = msg.data
  message_response = JSON.parse(rawJson)
end

ws.on :open do
  ws.send "\"subscribe\":\"blocks\""
end

ws.on :close do |e|
  puts "WEBSOCKET HAS CLOSED #e"
  exit 1
end

ws.on :error do |e|
  puts "WEBSOCKET ERROR #e"
end

如果没有任何形式的“保持活动”,连接会在大约 45 秒内关闭。我应该如何发送“心跳”数据包?似乎连接是由他们的服务器关闭的,而不是我的。

【问题讨论】:

Keeping the WebSocket connection alive 的可能重复项 类似,但问题不同。由于缺乏响应,我在 toshi 切断连接时遇到了麻烦——如果他们没有这种行为,那么连接将是稳固的。如果我定期发送一条消息说我仍在收听,我可以保持连接有效。 【参考方案1】:

您可以使用Websocket Eventmachine Client gem 发送心跳:

require 'websocket-eventmachine-client'

EM.run do
  ws = WebSocket::EventMachine::Client.connect(:uri => 'wss://bitcoin.toshi.io/')
  puts ws.comm_inactivity_timeout
  ws.onopen do
    puts "Connected"
  end

  ws.onmessage do |msg, type|
    puts "Received message: #msg"
  end

  ws.onclose do |code, reason|
    puts "Disconnected with status code: #code"
  end

  EventMachine.add_periodic_timer(15) do
    ws.send ""
  end
end

你可以用EM::add_periodic_timer(interval_in_seconds)为EventMachine设置定时器,然后用它发送你的心跳。

【讨论】:

我可以让它工作,直到包括EventMachine.next_tick,我最终得到error code 1002。你说我可以在#next_tick查看当前时间是什么意思? @Skull1234567 我修正了我的答案。你实际上应该使用#add_periodic_timer 而不是#next_tick——现在它可以工作了。 如何关闭此连接以及如何停止周期性计时器?【参考方案2】:

如果您使用Iodine's Websocket 客户端,您可以使用自动 ping 功能(默认且无法关闭):

require 'iodine/http'
# prevents the Iodine's server from running
Iodine.protocol = :timer
# starts Iodine while the script is still running
Iodine.force_start!
# set pinging to a 40 seconds interval.
Iodine::Http::Websockets.default_timeout = 40

settings = 
# set's the #on_open event callback.
settings[:on_open] = Proc.new do
    write 'sending this connection string.'
end
# set's the #on_message(data) event callback.
settings[:on_message] = Proc.new  |data| puts "Received message: #data" 
# connects to the websocket
Iodine::Http.ws_connect 'ws://localhost:8080', settings

这是一个相当基本的客户端,但也易于管理。

编辑

Iodine 还包括一些 cookie 和自定义标头的支持,如现在在 Iodine's documentation 中所见。因此可以使用不同的身份验证技术(身份验证标头或 cookie)。

【讨论】:

对不起,如果这是一个新手问题,但是一旦连接,我如何发送ws.send "\"subscribe\":\"blocks\""类型的消息? @Skull1234567 - 不用担心。我更新了我的答案。您使用 websocket 对象(事件对象)来发送数据或关闭连接。您可以找到Websocket event object here 的文档。

以上是关于如何在 ruby​​ on rails 中通过 websocket 发送保持活动的数据包的主要内容,如果未能解决你的问题,请参考以下文章

在 ruby​​ on rails 3 中通过电子邮件创建订阅

Ruby on Rails 高级 JSON 序列化

在 Ubuntu 上为 Ruby on Rails 安装 PostgreSQL

有没有办法在 Ruby on Rails routes.rb 中定义没有“/new”的新操作路径?

Ruby on Rails 中的基本图像大小调整

我是如何快速入门 Ruby on Rails 的