gpt4 book ai didi

PHP + SockJS + Redis : Unicast

转载 作者:可可西里 更新时间:2023-11-01 10:59:04 27 4
gpt4 key购买 nike

我的应用程序堆栈:

在我的服务器上运行着一个 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com