- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我的应用程序堆栈:
在我的服务器上运行着一个 Redis 服务器。 PHP 后端通过 Redis 服务器与 Predis 库进行通信。它将发布消息。这些消息将由我的 Redis 客户端 (node.js) 获取并推送到连接的 websocket 客户端(使用 SockJS)。
我的问题:
运行良好。至少对于广播消息。现在我到了需要发送单播消息的地步,但我被卡住了……如何将后端用户(消息发送者)与 websocket 的已连接客户端连接起来?
代码片段:
PHP
$redis = new Client();
$redis->publish('updates', Random::getUniqueString());
node.js 服务器上的 Redis 客户端
redis.subscribe('updates');
redis.on('message', function(channel, data) {
for (var id in sockets) {
if (sockets.hasOwnProperty(id)) {
sockets[id].write(data);
}
}
});
SockJS 客户端
mySocketFactory.setHandler('message', function(event) {
console.log(event.data);
});
就像我说的。运行良好,但 PHP 后端不知道用于套接字连接的 id
。
编辑:我想到的一个想法是使用 cookie。
最佳答案
我找到了解决问题的方法。建立套接字连接后,我向 PHP 后端发送请求并询问用户 ID。这存储在 node.js 服务器上。当消息传入时,会检查它们是否针对特定用户并仅为他们处理。
那么,我到底应该在我的 Node 服务器上存储什么?
var sockets = {}; // {connection_id: socket_connection}
var connIdToUser = {}; // {connection_id: user_id}
var connIdsForUser = {}; // {user_id: [connection_id_1, connection_id_2 ,...]}
socketServer.on('connection', function(conn) {
sockets[conn.id] = conn;
var options = {
host: os.hostname(),
port: 80,
path: '/user/id',
method: 'GET'
};
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
var userId = JSON.parse(chunk).id;
connIdToUser[conn.id] = userId;
if (!connIdsForUser.hasOwnProperty(userId)) {
connIdsForUser[userId] = [];
}
connIdsForUser[userId].push(conn.id);
console.log('connection id ' + conn.id + ' related to user id ' + userId);
});
});
req.end();
conn.on('close', function() {
console.log('connection lost ' + conn.id);
// remove connection id from stack for user
var connections = connIdsForUser[connIdToUser[conn.id]];
var index = connections.indexOf(conn.id);
if (index > -1) {
connections.splice(index, 1);
}
// remove connection at all
delete sockets[conn.id];
// remove relation between connection id and user
delete connIdToUser[conn.id];
});
});
将用户 ID 和连接 ID 之间的关系存储两次的原因是我需要发送消息或删除关闭事件的连接的不同用例。否则我将不得不使用嵌套循环。如您所见,删除套接字非常容易。尽管从用户的连接堆栈中删除连接有点复杂。
让我们继续发送消息。在这里,我定义了从 Redis 服务器获取的消息的结构:
{
targets: [], // array of unit ids (can be empty)
data: <mixed> // the real data
}
将数据发送到套接字如下所示:
redis.on('message', function(channel, message) {
message = JSON.parse(message);
// unicast/multicast
if (message.targets.length > 0) {
message.targets.forEach(function(userId) {
if (connIdsForUser[userId] !== undefined) {
connIdsForUser[userId].forEach(function(connId) {
sockets[connId].write(message.data);
});
}
});
// broadcast
} else {
for (var id in sockets) {
if (sockets.hasOwnProperty(id)) {
sockets[id].write(message.data);
}
}
}
});
由于我为每个用户存储了连接堆栈,因此很容易将数据发送到与特定用户相关的所有套接字。因此,我现在可以做的是单播(具有一个用户 ID 的数组)、多播(具有多个用户 ID 的数组)和广播(空数组)。
它在我的用例中运行良好。
关于PHP + SockJS + Redis : Unicast,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33089262/
我的应用程序堆栈: 在我的服务器上运行着一个 Redis 服务器。 PHP 后端通过 Redis 服务器与 Predis 库进行通信。它将发布消息。这些消息将由我的 Redis 客户端 (node.j
我刚刚为集群创建了三个专用主节点和一个数据节点。 现在,我需要配置将被发现和形成集群的节点的初始列表。 我包括了三个专用主节点的IP地址作为discovery.zen.ping.unicast.hos
我正在通过 ansible 设置 KVM 自动化,我有一个 VM 不断给我这个错误: libvirtError:XML 错误:预期的单播 MAC 地址,发现多播 '53:54:00:b4:ad:81'
CentOS上的Elasticsearch 1.7.x 设置一个3节点群集。 IP地址是: 192.168.3.100 192.168.3.101 192.168.3.102 为了简单起见,我们想在所
我从某个时候开始使用 RxJS,我似乎无法理解为什么我们将 RxJS Subject 称为 Multicast ,将 Observable 称为 Unicast 。 我知道 Subject 能够使用
我是一名优秀的程序员,十分优秀!