使用faye-websocket和EventMachine,代码与faye-websocket的客户端示例非常相似:
require 'faye/websocket'
require 'eventmachine'
def setup_socket(url)
EM.run {
ws = Faye::WebSocket::Client.new(url)
ws.on :open do ... end
ws.on :message do ... end
ws.on :close do ... end
}
end
我希望并行打开多个连接。由于执行不会退出setup_socket
子句,因此我无法多次调用EM.run
。我尝试在不同的主题中多次运行setup_socket
:
urls.each do |url|
Thread.new { setup_socket(url) }
end
但由于puts
语句无法达到输出,因此似乎没有做任何事情。
我不限于使用faye-websocket,但似乎大多数人都使用这个库。如果可能的话,我想避免多线程。我也不想失去改变的可能性(例如添加新的websocket)。因此,不希望在EM.run
子句中移动URL的迭代,而是启动多个EM会更有益。我以一种非常干净的方式找到了example for starting multiple servers via EM。我正在寻找类似的东西。
如何同时连接多个WebSockets?
答案 0 :(得分:2)
这是一种方法。
首先,您必须接受EM线程需要运行。没有这个线程,您将无法处理任何当前连接。所以你无法解决这个问题。
然后,为了向EM线程添加新URL,您需要一些方法从主线程到EM线程进行通信,因此您可以告诉它启动新连接。这可以使用EventMachine::Channel
完成。
所以我们现在可以建立的是这样的:
@channel = EventMachine::Channel.new
Thread.new {
EventMachine.run {
@channel.subscribe { |url|
ws = Faye::...new(url)
...
}
}
}
然后在主线程中,只要你想在事件循环中添加新的URL,就可以使用它:
def setup_socket(url)
@channel.push(url)
end
答案 1 :(得分:0)
以下是另一种方法...使用Iodine的原生websocket支持(或Plezi framework)代替em-websocket
......
......我有偏见(我是作者),但我认为他们让事情变得容易多了。此外,Plezi提供Redis自动缩放功能,因此很容易实现。
这是一个使用Plezi的例子,其中每个Controller都像一个频道,它有自己的URL和Websocket回调(尽管我认为Plezi的自动调度比下层更容易on_message
回调)。此代码可以放在config.ru
文件中:
require 'plezi'
# Once controller / channel for all members of the "Red" group
class RedGroup
def index # HTTP index for the /red URL
"return the RedGroup client using `:render`".freeze
end
# handle websocket messages
def on_message data
# in this example, we'll send the data to all the members of the other group.
BlueGroup.broadcast :handle_message, data
end
# This is the method activated by the "broadcast" message
def handle_message data
write data # write the data to the client.
end
end
# the blue group controller / channel
class BlueGroup
def index # HTTP index for the /blue URL
"return the BlueGroup client using `:render`".freeze
end
# handle websocket messages
def on_message data
# in this example, we'll send the data to all the members of the other group.
RedGroup.broadcast :handle_message, data
end
# This is the method activated by the "broadcast" message
def handle_message data
write data
end
end
# the routes
Plezi.route '/red', RedGroup
Plezi.route '/blue', BlueGroup
# Set the Rack application
run Plezi.app
P.S。
我也写了这个答案,因为在某些情况下em-websocket
可能会失败或占用资源。我不确定详细信息,但在websocket-shootout benchmark和AnyCable Websocket Benchmarks都注意到了。