Ruby 怎样使用 websocket 建立 one to one 的聊天
我最近在学习 websocket-rails (https://github.com/websocket-rails/websocket-rails), 可以用来建立多人聊天室,但是不知道怎么建立one to one的聊天,类似qq的私人聊天, 我没有找到相关的api. 请指点下,谢谢.
socket.io我也看了下,他有提供private message这个event,可以监听from和to.
ruby-china的通知机制也类似,推送到个人. 于是我参考了ruby-china的代码,发现是用的faye-rails (https://github.com/jamesotron/faye-rails).
主要逻辑如下:
服务器:
# https://github.com/ruby-china/ruby-china/blob/master/app/models/notification/base.rb#L20
# coding: utf-8
class Notification::Base
store_in collection: 'notifications'
field :read, default: false
belongs_to :user
index read: 1
index user_id: 1, read: 1
scope :unread, -> { where(read: false) }
after_create :realtime_push_to_client
after_update :realtime_push_to_client
def realtime_push_to_client
if self.user
hash = self.notify_hash
hash[:count] = self.user.notifications.unread.count
FayeClient.send("/notifications_count/#{self.user.temp_access_token}", hash) # 注意self.user.temp_access_token 和 FayeClient
end
end
end
# https://github.com/ruby-china/ruby-china/blob/55a3b35d9bd3db028221a4b6470a2f4e04c802dd/app/models/faye_client.rb
# faye_client.rb
require 'net/http'
class FayeClient
def self.send(channel, params)
Thread.new {
params[:token] = Setting.faye_token
message = {channel: channel, data: params}
uri = URI.parse(Setting.faye_server)
Net::HTTP.post_form(uri, message: message.to_json)
}
end
end
# user model
def temp_access_token
Rails.cache.fetch("user-#{self.id}-temp_access_token-#{Time.now.strftime("%Y%m%d")}") do
SecureRandom.hex
end
end
客户端:
initNotificationSubscribe : () ->
return if not App.access_token?
faye = new Faye.Client(App.faye_client_url)
faye.subscribe "/notifications_count/#{App.access_token}", (json) ->
span = $("#user_notifications_count span")
new_title = document.title.replace(/^\(\d+\) /,'')
if json.count > 0
span.addClass("badge-error")
new_title = "(#{json.count}) #{new_title}"
url = App.fixUrlDash("#{App.root_url}#{json.content_path}")
console.log url
$.notifier.notify("",json.title,json.content,url)
else
span.removeClass("badge-error")
span.text(json.count)
document.title = new_title
true
具体来说通过token来区分和维护多个channel, 即每一个用户和server之间酒有一个channel, 不过faye-rails不是走的websocket.
见官网Faye is a publish-subscribe messaging system based on the Bayeux protocol.
但是官方的架构有说:
# http://faye.jcoglan.com/architecture.html
Persistent connections using WebSocket
Long-polling via HTTP POST
Cross Origin Resource Sharing
Callback-polling via JSON-P
这也是我疑惑不解的地方.可能作者加了websocket部分的实现.
也可以看看GoEasy文库的其他资料。