3

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

  1. How to implement a WebSocket client in a HTTP stream server? (It's OK to use another lib instead of Sinatra)
  2. 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!

Hangchen Yu
  • 325
  • 3
  • 12
  • I have the same problem, did you find a solution? – rolele Oct 25 '15 at 08:46
  • I forgot the details of solution. But you may update the version of Ruby to avoid this error (>=ruby-2.1 seems ok). I also added several microseconds of "sleep" between each two "write". Hope this can help you! – Hangchen Yu Oct 26 '15 at 12:57

1 Answers1

0

The problem happened some long time ago, and I forgot the details of the solution. But according to my weak memory, you may update the version of Ruby to avoid this error (>=ruby-2.1 seems ok). I also added several microseconds of "sleep" between each two "write".

I believe that the version of Ruby is the main reason. Sorry that I can't test it now.

Hangchen Yu
  • 325
  • 3
  • 12