我一段时间以来一直在使用Sinatra,现在我想通过Websockets推送数据向我的Web应用程序添加实时功能。
我已经成功地独立使用了' em-websocket '宝石,但是我无法编写一个Ruby文件,其中包含Sinatra Web服务器和Web Socket服务器。
我尝试将run!或start!方法放在单独的线程中运行,但没有成功。
有人成功过吗?
我希望它们在同一个文件中,这样可以在两个服务器之间共享变量。
我一段时间以来一直在使用Sinatra,现在我想通过Websockets推送数据向我的Web应用程序添加实时功能。
我已经成功地独立使用了' em-websocket '宝石,但是我无法编写一个Ruby文件,其中包含Sinatra Web服务器和Web Socket服务器。
我尝试将run!或start!方法放在单独的线程中运行,但没有成功。
有人成功过吗?
我希望它们在同一个文件中,这样可以在两个服务器之间共享变量。
没试过,但应该不难:
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实现,可直接与Thin/Rainbows一起使用!如果您愿意,可以提取出来,这样您甚至不需要在另一个端口上运行服务器。
谢谢 Konstantin... 它起作用了!我稍微调整了一下你的代码。在我更改的地方添加了注释。
- 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
我偶然发现了这个websocket-rack GitHub项目,它基本上是一个Rack化的em-websocket,实际上我已经成功地将它与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
玩的开心!
Colin
我一直在使用sinatra-websocket,它允许您在与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>
请注意,您也可以使用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
Sinatra
类中设置的Rack::Server::Cookie
值,在客户端传递给ws.onopen
的handshake
中返回。请参阅我的更详细的问题:https://dev59.com/aXHYa4cB1Zd3GeqPNJnb - Dave Sag