【问题标题】:Private messaging using sockjs-tornado使用 sockjs-tornado 的私人消息传递
【发布时间】:2016-03-31 09:15:42
【问题描述】:

我已经使用 sockjs-tornado 实现了聊天功能,并且可以将消息存储在 RethinkDB 中。

您能否帮助我了解如何在 sockjs-tornado 中建立用于消息传递的私人渠道? (我的意思是私人对话/一对一)

下面是我的服务器端代码中的 on_message 函数 -

def on_message(self, message):
    str=message
    mg=str.split('#:#')
    sender=1 # This is the sender user id
    receiver=2 #This is the receiver user id - I need to implement session variables to have these id's so that I can use it here this way
    ts=r.expr(datetime.now(r.make_timezone('00:00')))
    connection = r.connect(host="192.x.x.x")
    r.db("djrechat").table('events').insert({"usrs":mg[0],"msg":mg[1],"tstamp":ts,"snder":sender,"rcver":receiver}).run(connection)
    log.info(message)
    self.broadcast(self.participants, '{} - {}'.format(self.stamp(),message))

目前正在向所有连接的客户端广播。 可能我应该有一个通道 id 并且只向两个具有相同通道 id 的客户端发送消息,但是我该如何实现它或者有没有更好的解决方案呢?

在客户端,我有以下 javascript -

      function connect() {
        disconnect();
        conn = new SockJS('http://localhost:8080/chat', ['websocket','xhr-streaming','iframe-eventsource','iframe-htmlfile','xhr-polling','iframe-xhr-polling','jsonp-polling']);
        //log('Connecting.....');
        conn.onopen = function() {
        //  log('Connected. (' + conn.protocol + ')');
        log('Connected.');
        };

        conn.onmessage = function(e) {
          log(e.data);
        };

        conn.onclose = function() {
          log('Disconnected.');
          conn = null;
        };
      }

我正在使用 python 3.4 - Django 1.8.4 和 Rethinkdb

【问题讨论】:

    标签: python django python-3.x tornado sockjs-tornado


    【解决方案1】:

    我的回答是假设当前解决方案中的所有客户端都连接到 SockJS 服务器,其频道名称用于聊天消息的广播(或接近此场景的名称)。我进一步假设用户从客户端发送消息时的往返是:

    [Sender (Client)] ------- Message (POST) --> [App Server] --- Message --> [Database]
                                                      |
                                                   Message
                                                      v
    [Receiver(s) (Client)] <-- Message (WS) -- [SockJS Server]
    

    这个问题有多种解决方案。我将在这里只概述我认为最简单和最强大的一个:

    • 除了聊天中的广播频道之外,每个用户(私人)频道让每个用户订阅。如果您实施此解决方案,唯一的额外更改是让应用服务器知道必须发送给接收者的私人的私人消息强>渠道。

    另一种稍微复杂且不优雅的解决方案是在需要时为每个私有对创建 ad hoc 频道。但是,您将如何让 User BUser A想和User B聊天时订阅(新创建的)私人频道?一种方法是广播请求User B 连接到该频道,但这会告诉所有其他客户端(在代码级别)将要进行的私人聊天;如果这些客户端中的任何一个遭到入侵,则该信息可能会被滥用,例如窃听或破坏私人方。

    其他建议

    我还想提一下,自从我写了我的sockjs - example of implementing rooms 答案后,我已经将自己的架构更改为(仍然)在前端使用SockJS,但RabbitMQ 使用Web-STOMP plugin on后端。这样一来,

    1. 客户端仍然在浏览器中使用sockjs-clientstomp-websocket
    2. 处理前端多路复用的所有后端代码可以删除
    3. (基于 RabbitMQ)后端快速非常强大
    4. 客户端向后端应用服务器发布一条消息,后端应用服务器依次
      1. 将消息保存在数据库中,
      2. 充当 RabbitMQ 服务器的客户端,(1) 将消息广播给所有连接的用户,或者如果消息是私有 (2) 如上述建议的解决方案所述,通过收件人自己的私人渠道将消息发送给单个收件人。

    全新的解决方案位于终止 HTTPS 和 SSL/TLS 加密的 WebSocket 连接的 HAProxy 之后。

    【讨论】:

    • 非常感谢 Martin 分享有用的信息!
    • 我将尝试调整我之前想到的第一个,但不确定如何让我的服务器识别传入的 msg 是通过私有通道并将消息仅推送到该私有通道客户端..我会尝试实现。
    • 嗨马丁,你能帮我提供私人消息代码吗?我尝试了不同的方式,但无法实现一对一的消息传递。基于 RabbitMQ 也很好。唯一的问题是它应该支持 python 3.4
    • @Sathish,您是否开始在后端使用带有 Web-STOMP 的 RabbitMQ,就像我上面建议的那样?因为如果是这样,从 RabbitMQ 3.5.7 版(或者更好的 3.6.0 版)开始,实现私有通道变得更加容易。知道这一点将有助于我编写伪代码。
    【解决方案2】:

    虽然 sockjs-tornado 没有实现通道或房间之类的东西,但有example multiplex 可以实现它。另请查看sockjs - example of implementing rooms。解决方案基于结构化的msg - 在消息中向您发送附加信息 - 频道名称。

    【讨论】:

    • 我尝试使用 conn.send({'method': 'set-channel', 'data': {'channel': channel_id}}) ,channel_id 是我的 onopen 中 'senderid&receiveid' 的组合客户端的事件..但它失败了,我在控制台中没有看到错误..不确定如何实现一对一的消息传递
    • 检查房间示例是否有帮助
    • 非常感谢您提供的示例!
    猜你喜欢
    • 2012-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 2011-03-22
    相关资源
    最近更新 更多