2012-05-05 6 views
3

Ruby 1.9.3およびThin 1.3.1を使用して、同じポートを使用して、通常のHTTPトラフィックだけでなく、Cramp(EventMachineの上に構築されています)経由でHTML5 Webソケットを提供しようとしています。ここでは、最小限の、自己完結型の例である:同じポート上にCramp :: Websocketと通常のRackアプリケーションを提供するには?

require 'thin' 
require 'cramp' 
require 'http_router' 

Cramp::Websocket.backend = :thin 

class SocketApp < Cramp::Action 
    self.transport = :websocket 

    on_start = :connected 
    on_finish = :disconnected 
    on_data = :message 

    def connected 
    puts 'Client connected' 
    end 
    def disconnected 
    puts 'Client disconnected' 
    end 
    def message(msg) 
    puts "Got message: #{msg}" 
    render 'Here is your reply' 
    end 
end 

class WebApp 
    def call(env) 
    [ 200, { 'Content-Type' => 'text/html' }, <<EOF 
<html><head> 
<script> 
    function init() { 
    function log(msg) { document.getElementById('log').innerHTML += msg + '<br>'; } 
    var socketUri = 'ws://' + document.location.host + '/socket'; 
    log('Socket URI: ' + socketUri); 
    var socket = new WebSocket(socketUri); 
    socket.onopen = function(e) { 
     log('onopen'); 
     socket.send('Is there anybody out there?'); 
     log('sent message'); 
    }; 
    socket.onclose = function(e) { 
     log('onclose; code = ' + e.code + ', reason = ' + e.reason); 
    }; 
    socket.onerror = function(e) { 
     log('onerror'); 
    }; 
    socket.onmessage = function(e) { 
     log('onmessage; data = ' + e.data); 
    }; 
    } 
</script> 
</head><body onload='init();'> 
    <h1>Serving Cramp::Websocket and normal Rack app on the same port</h1> 
    <p id='log'></p> 
</body></html> 
EOF 
    ] 
    end 
end 

app = HttpRouter.new do 
    add('/socket').to SocketApp 
    add('/').to WebApp.new 
end 

run app 

あなたは、自分のためにこれを試してみてくださいconfig.ruという名前のファイルにこのコードを貼り付けしてthin startを実行したい場合。 thincramphttp_routerがインストールされている必要があります。

考えられるのは、JavaScriptコードがWebSocket接続をws://localhost:3000/socketにして送信されたメッセージをエコーし​​ますが、意図したとおりに動作しないという考えです。 openイベントが発生すると、メッセージの送信時にエラーは発生しませんが、応答は得られません。

Client connectedメッセージが印刷されないため、サーバーの観点からは接続されていません。

thin start -Dを使用すると、HTTP 101が発生し、一部のバイナリデータが交換されていることがわかります。

私は間違っていますか?

更新:私は2つの部分にファイルを分割した場合、HttpRouterをリッピングし、異なるポート上の2つのthinのインスタンスを実行し、それはまだ動作しません。問題はソケットコードにあり、HttpRouterまたはWebAppではなくです。

答えて

3

これは不正行為ですが、最終的に別のライブラリに切り替えることで解決しました:websocket-rack。不思議なことに、修正されたコードは次のとおりです。

require 'thin' 
require 'http_router' 
require 'rack/websocket' 

class SocketApp < Rack::WebSocket::Application 
    def on_open(env) 
    puts 'Client connected' 
    end 
    def on_close(env) 
    puts 'Client disconnected' 
    end 
    def on_message(env, message) 
    puts "Got message: #{message}" 
    send_data 'Here is your reply' 
    end 
end 

class WebApp 
    def call(env) 
    [200, { 'Content-Type' => 'text/html' }, <<EOF 
<html><head> 
<script> 
    function init() { 
    function log(msg) { document.getElementById('log').innerHTML += msg + '<br>'; } 
    var socketUri = 'ws://' + document.location.host + '/socket'; 
    log('Socket URI: ' + socketUri); 
    var socket = new WebSocket(socketUri); 
    socket.onopen = function(e) { 
     log('onopen'); 
     socket.send('Is there anybody out there?'); 
     log('sent message'); 
    }; 
    socket.onclose = function(e) { 
     log('onclose; code = ' + e.code + ', reason = ' + e.reason); 
    }; 
    socket.onerror = function(e) { 
     log('onerror'); 
    }; 
    socket.onmessage = function(e) { 
     log('onmessage; data = ' + e.data); 
    }; 
    } 
</script> 
</head><body onload='init();'> 
    <h1>Serving WebSocket and normal Rack app on the same port</h1> 
    <p id='log'></p> 
</body></html> 
EOF 
    ] 
    end 
end 

app = HttpRouter.new do 
    add('/socket').to(SocketApp.new) 
    add('/').to(WebApp.new) 
end 

run app 
関連する問題