在 Rails 中使用 em-websocket 构建对讲系统的策略?
Posted
技术标签:
【中文标题】在 Rails 中使用 em-websocket 构建对讲系统的策略?【英文标题】:The stratigy of build a talk-to-talk system using em-websocket in rails? 【发布时间】:2015-12-29 06:21:42 【问题描述】:也许这是服务器推送系统的一个很好的例子。系统中有很多用户,用户可以互相交谈。可以这样完成:一个用户(通过 websocket)向服务器发送消息,然后服务器将消息转发给另一个用户。关键是找到ws(websocket object)和用户之间的绑定。示例代码如下:
EM.run
EM::WebSocket.run(:host => "0.0.0.0", :port => 8080, :debug => false) do |ws|
ws.onopen |handshake|
# extract the user id from handshake and store the binding between user and ws
ws.onmessage |msg|
# extract the text and receiver id from msg
# extract the ws_receiver from the binding
ws_receiver.send(text)
end
我想弄清楚以下问题:
ws
对象可以序列化以便存储到磁盘或数据库中吗?否则我只能将绑定存储到内存中。
em-websocket 和 websocket-rails 有什么区别?
你推荐哪个 gem 用于 websocket?
【问题讨论】:
【参考方案1】:您正在接近 websocket 非常适合的用例,因此您走在正确的轨道上。
-
您可以使用 Marshal 序列化
ws
对象,但将 websocket 对象视为有点像 http 请求对象,因为它们是一种通信类型的抽象。您可能最好对数据进行编组/存储。
em-websocket 是一个或多或少直接在网络机器上构建的较低(ish)杠杆 websocket 库。 websocket-rails 是对 websockets 的更高层次的抽象,内置了很多不错的工具和非常好的文档。它建立在faye-websocket-rails 之上,而faye-websocket-rails 本身是建立在网络机器上的。 *注意,作为 Rails 5 的新 websocket 库的 action cable 是基于 faye 构建的。
我过去使用过 websocket-rails,我很喜欢它。它会为你照顾很多。但是,如果您可以使用 Rails 5 和 Action Cable,那就去做吧,这就是未来。
【讨论】:
感谢您分享您的经验。我可以从你的回答中找到 rails 中 websocket 的趋势。也许正在开发rails 5,我仍然使用rails 4.2.5。但是 rails 5 是趋势,所以最后我将使用它与 Action Cable。谢谢! 你可能会很好地尝试 websocket-rails 或 faye,因为它们都会让你进入 Rails 5 的正确参考框架。 @ChaseGilliam - 我注意到 websocket-rails 自 2014 年 6 月 5 日以来一直没有更新... Rails 从那时起从 4.1.x 移动到 4.2.x (虽然我不知道有多少这可能会影响 gem 的可集成性)...但可能是 Faye、em-websocket、ActionCable 和 Plezi 是镇上唯一的游戏。【参考方案2】:以下是对Chase Gilliam's succinct answer 的补充,其中包括对em-websocket、websocket-rails(很久没有维护)、faye-websocket-rails 和ActionCable 的引用。
我会推荐Plezi 框架。它既可用作独立的应用程序框架,也可用作 Rails Websocket 增强功能。
我也会考虑以下几点:
您是否需要在连接之间保留消息(即,如果其他用户离线,消息是否应该在“消息框”中等待?消息应该等待多长时间?)...?
您希望保留消息历史记录吗?
这些要点将帮助您决定是否为消息使用持久存储(即数据库)。
即,要将 Plezi 与 Rails 一起使用,请在应用程序的 config/initializers
文件夹中创建一个 init_plezi.rb
。使用(作为示例)以下代码:
class ChatDemo
# use JSON events instead of raw websockets
@auto_dispatch = true
protected #protected functions are hidden from regular Http requests
def auth msg
@user = User.auth_token(msg['token'])
return close unless @user
# creates a websocket "mailbox" that will remain open for 9 hours.
register_as @user.id, lifetime: 60*60*9, max_connections: 5
end
def chat msg, received = false
unless @user # require authentication first
close
return false
end
if received
# this is only true when we sent the message
# using the `broadcast` or `notify` methods
write msg # writes to the client websocket
end
msg['from'] = @user.id
msg['time'] = Plezi.time # an existing time object
unless msg['to'] && registered?(msg['to'])
# send an error message event
return event: :err, data: 'No recipient or recipient invalid'.to_json
end
# everything was good, let's send the message and inform
# this will invoke the `chat` event on the other websocket
# notice the `true` is setting the `received` flag.
notify msg['to'], :chat, msg, true
# returning a String will send it to the client
# when using the auto-dispatch feature
event: 'message_sent', msg: msg.to_json
end
end
# remember our route for websocket connections.
route '/ws_chat', ChatDemo
# a route to the javascript client (optional)
route '/ws/client.js', :client
Plezi 设置了它自己的服务器(Iodine,一个 Ruby 服务器),因此请记住从您的应用程序中删除对 puma
、thin
或任何其他自定义服务器的任何引用。
在客户端,您可能想要使用 Plezi 提供的 Javascript 助手(它是可选的)...添加:
<script src='/es/client.js' />
<script>
TOKEN = <%= @user.token %>;
c = new PleziClient(PleziClient.origin + "/ws_chat") // the client helper
c.log_events = true // debug
c.chat = function(event)
// do what you need to print a received message to the screen
// `event` is the JSON data. i.e.: event.event == 'chat'
c.error = function(event)
// do what you need to print a received message to the screen
alert(event.data);
c.message_sent = function(event)
// invoked after the message was sent
// authenticate once connection is established
c.onopen = function(event)
c.emit(event: 'auth', token: TOKEN);
// // to send a chat message:
// c.emitevent: 'chat', to: 8, data: "my chat message"
</script>
我没有测试实际的消息代码,因为它只是一个骨架,而且它需要一个带有 User
模型和 token
的 Rails 应用程序,我不想编辑只是为了回答一个问题(不冒犯)。
【讨论】:
以上是关于在 Rails 中使用 em-websocket 构建对讲系统的策略?的主要内容,如果未能解决你的问题,请参考以下文章