Ruby Sinatra与EventMachine WebSockets合作是否成功?

Ruby Sinatra与EventMachine WebSockets合作是否成功?,ruby,sinatra,websocket,rack,eventmachine,Ruby,Sinatra,Websocket,Rack,Eventmachine,我使用Sinatra已经有一段时间了,我想通过WebSocket推送数据,为我的web应用程序添加一些实时功能 我已经成功地单独使用了gem'em websocket',但是还不能编写一个包含sinatra web服务器和web套接字服务器的ruby文件 我试过旋转跑步!或者开始!方法在单独的线程中关闭,但没有成功 有人用过这个吗 我希望将它们放在同一个文件中,以便在两台服务器之间共享变量 谢谢 没有尝试,但不应该太难: require 'em-websocket' require 'sinat

我使用Sinatra已经有一段时间了,我想通过WebSocket推送数据,为我的web应用程序添加一些实时功能

我已经成功地单独使用了gem'em websocket',但是还不能编写一个包含sinatra web服务器和web套接字服务器的ruby文件

我试过旋转跑步!或者开始!方法在单独的线程中关闭,但没有成功

有人用过这个吗

我希望将它们放在同一个文件中,以便在两台服务器之间共享变量


谢谢

没有尝试,但不应该太难:

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
需要“em websocket”
需要“sinatra/基地”
需要“瘦”
嗯,跑吧
类应用程序'0.0.0.0',:port=>3001)do
#这里是Websocket代码
结束
#你也可以用彩虹!而不是瘦。
#任何基于EM的机架处理器都应该这样做。
精简::Server.start应用程序,“0.0.0.0”,3000
结束

此外,它还有一个websocket实现,可以直接使用瘦/彩虹!您可能能够提取,因此您甚至不需要在另一个端口上运行服务器。

谢谢Konstantin。。。成功了!我不得不稍微修改一下你的代码。我在修改的地方添加了评论

-波尔


require'rubygems'#8080)do | ws |##FYI,您也可以将Padrino应用程序与EventMachine一起使用(因为它们是Sinatra应用程序的子集):

干杯, Mike

我偶然发现了这个github项目,它基本上是一个机架化的项目,实际上它与一个Sinatra应用程序并行运行。这是我的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
需要“rubygems”
需要“机架/网匣”
需要“sinatra/基地”
类WebSocketApp
玩得开心
科林

我一直在用。它允许您在与Sinatra相同的进程和端口上运行websocket服务器

免责声明:我是维护者

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>
需要“sinatra”
需要“sinatra websocket”
设置:服务器“精简”
集合:套接字,[]
获取“/”do
如果!请求websocket?
雇员再培训局:索引
其他的
request.websocket do | ws|
ws.onopen do
发送(“你好,世界!”)

settings.sockets..这是将websocket与sinatra一起使用的最快的方法(在我看来),我能问一下与使用'em websocket',将sinatra::Base子类化,以及“手动”插入事件循环相比,这种方法带来了哪些缺点吗?还有谁能简单解释一下为什么“下一步”是什么这里需要吗?@@Simulare--有什么办法可以在负载平衡的设置中工作吗?我的意思是,从上面的例子来看,每个Sinatra进程都会有自己的“settings.sockets”数组,从而使进程变为有状态?非常可爱:)这很好。不过有一个问题,EventMachine套接字事件如何访问会话信息以验证事件是否来自经过适当身份验证的用户?根据我对@Konstanti Haase的回答的评论,我已经概述了这一点,这是一个新问题-请看,这就是我所做的。然而,我有一个相关的问题,那就是如何解码客户端传递给
ws.onopen
握手中返回的
Rack::Server::Cookie
(在
Sinatra
类中设置)值。查看我的问题的更多细节,他字面上说“这是我的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
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>