I write a HTTP server (A) using Sinatra::Streaming (I use Ruby). It needs to read data from a WebSocket server (B) and forward it to a client (C). The data flow is "B-->A-->C". The read and write operations should be in real time.
As a possible solution, I attempted to create a WebSocket connection in Sinatra. The code is like this:
class Deploy < Sinatra::Base
helpers Sinatra::Streaming
set :sessions, true
set :server, 'thin'
get '/' do
stream(:keep_open) do |out|
#create a WebSocket connection
EM.run {
ws = Faye::WebSocket::Client.new('ws://0.0.0.0:8080/')
ws.on :message do |event|
out << event.data
out.flush
end
ws.on :close do |event|
ws = nil
end
}
end
end
end
I have tried several WebSocket Client lib such as faye-websocket. The program failed as ~/.rvm/gems/ruby-2.0.0-p598/gems/sinatra-contrib-1.4.2/lib/sinatra/streaming.rb:100:in '<<': not opened for writing (IOError)
when executing out << event.data
. The WebSocket connection was closed at the same time.
It seems that the IO of WebSocket conflicts/closes the IO of Sinatra Stream.
I currently create a subprocess to establish the WebSocket connection, and let the subprocess communicate with Sinatra sever (A). But it may consume too many system resources if tens of people access to A. What's more, Sinatra Stream server also often aborts for not opened for writing (IOError)
when there are too many clients or too long waiting time.
So my question is
- How to implement a WebSocket client in a HTTP stream server? (It's OK to use another lib instead of Sinatra)
- If a WebSocket client could be implemented in Sinatra Stream, how to improve the stability of Sinatra Stream sever? (Avoid IOError)
Sorry for my poor English. Thank you very much!