-->

How to send a keep-alive packet through websocket

2019-03-31 06:09发布

问题:

I want to send a

"Keep alive from client"

message every 30 seconds for my websocket connection. Here's what the code that I have in my websocket initializer looks like:

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

Without any sort of 'keep alive', the connect closes in about 45 seconds. How should I send the 'heart-beat' packet? It seems that the connection is closed by their server, not mine.

回答1:

You can use Websocket Eventmachine Client gem to send hearbeat:

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

You can setup timer for EventMachine with EM::add_periodic_timer(interval_in_seconds), and then send your heartbeat with it.



回答2:

You can use the auto-ping feature (its default and can't be turned off) if you're using Iodine's Websocket client:

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

It's a fairly basic client, but also easy to manage.

EDIT

Iodine also includes some cookie and custom header's support, as now seen in Iodine's documentation. So it's possible to use different authentication techniques (authentication headers or cookies).