This is a serverside websocket client. I'm trying to get user input on a loop, then send that as a websocket message to a server. The basic actions are working and I can ping/pong the server. But it's not working to place a loop in the websocket on(:open)
function:
Client (excerpt):
require 'faye/websocket'
require 'eventmachine'
EM.run do
ws = Faye::WebSocket::Client.new('ws://localhost:3000/')
ws.on :message do |event|
puts event.data
end
ws.on :open do |event|
ws.send "predefined" # this works
ws.send gets.chomp # this does too
loop { ws.send gets.chomp } # this does not
end
end
Server (excerpt) which seems to be working fine:
def self.onmessage(request, ws, msg)
EM.next_tick { Sockets.each{|s| s.send msg.data } }
end
I think the issue is the loop blocks the on(:open)
function from returning and moving the event machine to the next tick.
I can unblock event machine using TickLoop:
def start_tick_loop
EM.tick_loop do
Ws.send gets.chomp
end.on_stop { EM.stop }
end
EM.run {
Ws.on :open do |event|
start_tick_loop
end
}
but this isn't ideal, because each client is blocked by gets.chomp
. I want the user input to not block the on(:message)
handler from working.
At the end of the day I suppose I can make a wrapper script which watches a file for changes, and send the gets.chomp
output there. But I was hoping there was a simpler way.
It ended up working to put a thread inside the tick loop:
EM.tick_loop do
Thread.new {
inp = gets.chomp
Ws.send inp
}
end.on_stop { EM.stop }