如何使用 Faye Websockets 向特定客户端发送消息?

How can I send messages to specific client using Faye Websockets?

我一直在开发一个网络应用程序,它本质上是一个使用 sinatra 的网络信使。我的目标是使用 pgp 加密所有消息,并使用 faye websocket 在客户端之间进行全双工通信。

我的主要问题是能够使用 faye 向特定客户端发送消息。除此之外,我在一个聊天室中的所有消息都为每个人保存了两次,因为它是 pgp 加密的。

到目前为止,我考虑过为每个客户端启动一个新的套接字对象并将它们存储在散列中。我不知道这种方法是否是最有效的方法。例如,我已经看到 socket.io 允许您发送给特定的客户端,但似乎不是使用 faye websockets 发送?我也在考虑使用 pub sub 模型,但我还是不确定。

感谢任何建议,谢谢!

我是 iodine's 作者,所以我的方法可能有偏见。

我会考虑通过使用的 ID 命名频道(即 user1...user201983 并将消息发送到用户的频道。

我觉得王菲会支持的。我知道在使用 iodine 原生 websockets 和内置 pub/sub 时,这是非常有效的。

So far I've thought of starting up a new socket object for every client and storing them in a hash...

这是一个很常见的错误,经常出现在简单的例子中。

它仅适用于单进程环境,您必须重新编写整个逻辑才能扩展您的应用程序。

通道方法允许您使用 Redis 或任何其他 Pub/Sub 服务进行扩展,而无需重新编写应用程序的逻辑。

这是一个简单的示例,您可以从 Ruby 终端 (irb) 运行。我使用 plezi.io 只是为了让代码更短一些:

require 'plezi'

class Example
  def index
    "Use Websockets to connect."
  end
  def pre_connect
    if(!params[:id])
      puts "an attempt to connect without credentials was made."
      return false
    end
    return true
  end
  def on_open
    subscribe channel: params[:id]
  end
  def on_message data
    begin
      msg = JSON.parse(data)
      if(!msg["to"] || !msg["data"])
        puts "JSON message error", data
        return
      end
      msg["from"] = params[:id]
      publish channel: msg["to"].to_s, message: msg.to_json
    rescue => e
      puts "JSON parsing failed!", e.message
    end

  end
end

Plezi.route "/" ,Example
Iodine.threads = 1
exit

要测试此示例,请使用 Javascript 客户端,可能是这样的:

// in browser tab 1
var id = 1
ws = new WebSocket("ws://localhost:3000/" + id)
ws.onopen = function(e) {console.log("opened connection");}
ws.onclose = function(e) {console.log("closed connection");}
ws.onmessage = function(e) {console.log(e.data);}
ws.send_to = function(to, data) {
    this.send(JSON.stringify({to: to, data: data}));
}.bind(ws);

// in browser tab 2
var id = 2
ws = new WebSocket("ws://localhost:3000/" + id)
ws.onopen = function(e) {console.log("opened connection");}
ws.onclose = function(e) {console.log("closed connection");}
ws.onmessage = function(e) {console.log(e.data);}
ws.send_to = function(to, data) {
    this.send(JSON.stringify({to: to, data: data}));
}.bind(ws);

ws.send_to(1, "hello!")