使用 sockjs-tornado 的私人消息传递
Private messaging using sockjs-tornado
我已经使用 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
虽然 sockjs-tornado 没有实现诸如通道或房间之类的东西,但是 example multiplex how one could implement that. Also look at sockjs - example of implementing rooms。解决方案基于结构化 msg
- 在消息中您发送了附加信息 - 频道名称。
我的回答假设当前解决方案中的所有客户端都连接到一个 SockJS 服务器,该服务器的频道名称用于聊天消息的广播(或接近此场景的名称)。我进一步假设用户从客户端发送消息时的往返行程是:
[Sender (Client)] ------- Message (POST) --> [App Server] --- Message --> [Database]
|
Message
v
[Receiver(s) (Client)] <-- Message (WS) -- [SockJS Server]
这个问题有多种解决方案。我这里只列出我认为最简单最稳健的:
- 让每个用户订阅一个每用户(私有)频道另外广播频道在聊天中。 如果您实施此解决方案,唯一的 附加 更改是让 应用程序服务器 知道私人消息必须 仅 发送到接收者的 私人 频道。
另一个稍微复杂且不优雅的解决方案是 在需要时为每个私有对创建 临时 通道。 但是,当 User A
想与 User B
聊天时,您如何让 User B
订阅(新创建的)私人频道?一种方法是 广播 请求 User B
连接到该频道,但这会告诉所有其他客户端(在代码级别)关于这个私人聊天发生;如果这些客户端中的任何一个受到威胁,该信息可能会被滥用,例如窃听或破坏私人派对。
其他建议
我还想提一下,因为我在后端写了 sockjs - example of implementing rooms answer, I have changed my own architecture to (still) use SockJS
in the front-end, but with RabbitMQ using the Web-STOMP plugin。这样,
- 客户端在浏览器中仍然使用sockjs-client with stomp-websocket,
- 处理前端多路复用的所有后端代码 可以删除,
- (基于 RabbitMQ 的)后端快速并且非常健壮,
- 客户端向后端应用服务器发送消息,后者又
- 将消息保存在数据库中,和
- 充当 RabbitMQ 服务器的客户端,并且 (1) 将消息广播给所有连接的用户,或者如果消息是 private (2) 通过收件人自己的私人渠道将消息发送给单个收件人,如上面建议的解决方案所述。
整个新解决方案置于 HAProxy 之后,它终止 HTTPS 和 SSL/TLS-encrypted WebSocket 连接。
我已经使用 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
虽然 sockjs-tornado 没有实现诸如通道或房间之类的东西,但是 example multiplex how one could implement that. Also look at sockjs - example of implementing rooms。解决方案基于结构化 msg
- 在消息中您发送了附加信息 - 频道名称。
我的回答假设当前解决方案中的所有客户端都连接到一个 SockJS 服务器,该服务器的频道名称用于聊天消息的广播(或接近此场景的名称)。我进一步假设用户从客户端发送消息时的往返行程是:
[Sender (Client)] ------- Message (POST) --> [App Server] --- Message --> [Database]
|
Message
v
[Receiver(s) (Client)] <-- Message (WS) -- [SockJS Server]
这个问题有多种解决方案。我这里只列出我认为最简单最稳健的:
- 让每个用户订阅一个每用户(私有)频道另外广播频道在聊天中。 如果您实施此解决方案,唯一的 附加 更改是让 应用程序服务器 知道私人消息必须 仅 发送到接收者的 私人 频道。
另一个稍微复杂且不优雅的解决方案是 在需要时为每个私有对创建 临时 通道。 但是,当 User A
想与 User B
聊天时,您如何让 User B
订阅(新创建的)私人频道?一种方法是 广播 请求 User B
连接到该频道,但这会告诉所有其他客户端(在代码级别)关于这个私人聊天发生;如果这些客户端中的任何一个受到威胁,该信息可能会被滥用,例如窃听或破坏私人派对。
其他建议
我还想提一下,因为我在后端写了 sockjs - example of implementing rooms answer, I have changed my own architecture to (still) use SockJS
in the front-end, but with RabbitMQ using the Web-STOMP plugin。这样,
- 客户端在浏览器中仍然使用sockjs-client with stomp-websocket,
- 处理前端多路复用的所有后端代码 可以删除,
- (基于 RabbitMQ 的)后端快速并且非常健壮,
- 客户端向后端应用服务器发送消息,后者又
- 将消息保存在数据库中,和
- 充当 RabbitMQ 服务器的客户端,并且 (1) 将消息广播给所有连接的用户,或者如果消息是 private (2) 通过收件人自己的私人渠道将消息发送给单个收件人,如上面建议的解决方案所述。
整个新解决方案置于 HAProxy 之后,它终止 HTTPS 和 SSL/TLS-encrypted WebSocket 连接。