2010-06-08 2 views
35

Я использую Sinatra на какое-то время, и я хотел бы добавить некоторые функции в реальном времени в свое веб-приложение, нажав данные через websockets.Любой успех с Sinatra, работающий вместе с EventMachine WebSockets?

Я сам использовал самоцвета «em-websocket», но не смог написать один файл ruby ​​с веб-сервером sinatra и сервером веб-сокетов.

Я пробовал вращаться! или начать! методы отключены в отдельных потоках без успеха.

Неужели кто-нибудь получил это на работу?

Я хочу, чтобы они были в том же файле, что и я, затем обмениваюсь переменными между двумя серверами.

Спасибо!

ответ

26

Не пробовал, но не должно быть слишком трудно:

require 'em-websocket' 
require 'sinatra/base' 
require 'thin' 

EM.run do 
    class App < Sinatra::Base 
    # Sinatra code here 
    end 

    EM::WebSocket.start(:host => '0.0.0.0', :port => 3001) do 
    # Websocket code here 
    end 

    # You could also use Rainbows! instead of Thin. 
    # Any EM based Rack handler should do. 
    Thin::Server.start App, '0.0.0.0', 3000 
end 

Кроме того, Cramp имеет реализацию WebSocket, которая работает непосредственно с тонкими/Rainbows! вы можете извлечь, поэтому вам даже не нужно будет запускать сервер на другом порту.

+0

Это почти так, как я это сделал. У меня есть связанный с этим вопрос, каким образом я могу декодировать «Rack :: Server :: Cookie» (установленный в классе 'Sinatra') значение, возвращенное в' handshake', переданное клиентом на 'ws.onopen'. См. Мой вопрос более подробно на http://stackoverflow.com/questions/16312024/how-to-decode-a-cookie-from-the-header-of-a-websocket-connection-handshake-rub –

20

Спасибо, Константин ... это сработало! Мне пришлось слегка настроить ваш код. Я добавил комментарии, где я его изменил.

-poul

require 'rubygems'  # <-- Added this require 
require 'em-websocket' 
require 'sinatra/base' 
require 'thin' 

EventMachine.run do  # <-- Changed EM to EventMachine 
    class App < Sinatra::Base 
     get '/' do 
      return "foo" 
     end 
    end 

    EventMachine::WebSocket.start(:host => '0.0.0.0', :port => 8080) do |ws| # <-- Added |ws| 
     # Websocket code here 
     ws.onopen { 
      ws.send "connected!!!!" 
     } 

     ws.onmessage { |msg| 
      puts "got message #{msg}" 
     } 

     ws.onclose { 
      ws.send "WebSocket closed" 
     } 

    end 

    # You could also use Rainbows! instead of Thin. 
    # Any EM based Rack handler should do. 
    App.run!({:port => 3000}) # <-- Changed this line from Thin.start to App.run! 
end 
+0

Это хорошо работает , Один вопрос, однако, как события EventMachine сокета получают доступ к информации сеанса для аутентификации того, что события происходят от правильно прошедшего проверку пользователя? –

+0

Я изложил это в соответствии с моим комментарием о ответе @ Konstanti Haase, как новый вопрос - см. Http://stackoverflow.com/questions/16312024/how-to-decode-a-cookie-from-the-header- –

7

FYI, вы можете также использовать Padrino приложения с EventMachine (так как они являются подмножествами Sinatra приложений):

require 'rubygems' 
require 'eventmachine' 
require 'padrino-core' 
require 'thin' 
require ::File.dirname(__FILE__) + '/config/boot.rb' 

EM.run do 
    Thin::Server.start Padrino.application, '0.0.0.0', 3000 
end 

Cheers, Майк

17

я споткнулся на этот проект websocket-rack github, который, в основном, был завален em-websocket и фактически получил его, чтобы хорошо работать бок о бок с Синой tra прилож. Вот мой config.ru:

require 'rubygems' 
require 'rack/websocket' 
require 'sinatra/base' 

class WebSocketApp < Rack::WebSocket::Application 
    # ... 
end 

class SinatraApp < Sinatra::Base 
    # ... 
end 

map '/ws' do 
    run WebSocketApp.new 
end 

map '/' do 
    run SinatraApp 
end 

Удачи!
Colin

+0

Колин - просто чтобы быть понятным, это в вашем файле config.ru? – wchrisjohnson

+2

Он буквально говорит: «Вот мой конфиг.ru: «Итак, я думаю, что« Да »- это ответ :) –

11

Я использую sinatra-websocket. Это позволит вам запустить сервер websocket в том же процессе и в том же порту, что и Sinatra.

Отказ от ответственности: Я сопровождающий.

require 'sinatra' 
require 'sinatra-websocket' 

set :server, 'thin' 
set :sockets, [] 

get '/' do 
    if !request.websocket? 
    erb :index 
    else 
    request.websocket do |ws| 
     ws.onopen do 
     ws.send("Hello World!") 
     settings.sockets << ws 
     end 
     ws.onmessage do |msg| 
     EM.next_tick { settings.sockets.each{|s| s.send(msg) } } 
     end 
     ws.onclose do 
     warn("websocket closed") 
     settings.sockets.delete(ws) 
     end 
    end 
    end 
end 

__END__ 
@@ index 
<html> 
    <body> 
    <h1>Simple Echo & Chat Server</h1> 
    <form id="form"> 
     <input type="text" id="input" value="send a message"></input> 
    </form> 
    <div id="msgs"></div> 
    </body> 

    <script type="text/javascript"> 
    window.onload = function(){ 
     (function(){ 
     var show = function(el){ 
      return function(msg){ el.innerHTML = msg + '<br />' + el.innerHTML; } 
     }(document.getElementById('msgs')); 

     var ws  = new WebSocket('ws://' + window.location.host + window.location.pathname); 
     ws.onopen = function() { show('websocket opened'); }; 
     ws.onclose = function() { show('websocket closed'); } 
     ws.onmessage = function(m) { show('websocket message: ' + m.data); }; 

     var sender = function(f){ 
      var input  = document.getElementById('input'); 
      input.onclick = function(){ input.value = "" }; 
      f.onsubmit = function(){ 
      ws.send(input.value); 
      input.value = "send a message"; 
      return false; 
      } 
     }(document.getElementById('form')); 
     })(); 
    } 
    </script> 
</html> 
+0

. Если это самый быстрый способ использования websocket с синатрой (на мой взгляд), могу ли я спросить, какие недостатки этот подход приносит по сравнению с использованием« em-websocket », , подклассификация Sinatra :: Base и «вручную» встраивание в цикл событий? –

+0

также может кто-нибудь дать короткое объяснение, почему здесь нужен «next_tick»? –

+0

@@ simulacre - Любые идеи, как сделать эту работу при загрузке сбалансированная настройка? Я имею в виду из приведенного выше примера, каждый процесс Sinatra имел бы свой собственный массив «settings.sockets», превращающий процесс в состояние «0»? – rebnoob

Смежные вопросы