2

我想获得一个多进程节点。工作人员正在监听客户端连接。我需要将套接字传递给主进程,因为主进程向客户端发出消息。工作人员还需要套接字来向客户端发出消息。

套接字是一个循环对象,不能传递给主进程。

我的代码:

const cluster = require('cluster');

const http = require('http');
var io = require('socket.io');

var users;
var clients = {};
if (cluster.isMaster) {

function messageHandler(msg) {
   if (msg.usersarray) {
      usersarray = msg.usersarray;
      console.log(usersarray);
   }else if(msg.socket){
      clients[usersarray["manu"][0]] = msg.socket;
      clients[usersarray["manu"][0]].emit("hola","hola");               
   }
}

// Start workers and listen for messages containing notifyRequest
const numCPUs = require('os').cpus().length;
for (var i = 0; i < numCPUs; i++) {
  cluster.fork();
}

Object.keys(cluster.workers).forEach((id) => {
  cluster.workers[id].on('message', messageHandler);
});


}else {

// Create server & socket

var server = http.createServer(function(req, res){
    // Send HTML headers and message
    res.writeHead(404, {'Content-Type': 'text/html'});
    res.end('<h1>Aw, snap! 404</h1>');
});
server.listen(3000);
io = io.listen(server);

// Add a connect listener
io.sockets.on('connection', function(socket) {
    var hs = socket.handshake;
    console.log("socket connected");    
    if(users == undefined){
        users = {};
    }

    if(hs.query.usuario != undefined){

        if(users[hs.query.usuario] == undefined){
            users[hs.query.usuario] = new Array();
        }    

        users[hs.query.usuario].push(socket.id); // connected user with its socket.id
        clients[socket.id] = socket; // add the client data to the hash
        process.send({ usersarray: users});
        process.send({ socket: socket});
    }

    // Disconnect listener
    socket.on('disconnect', function() {
        console.log('Client disconnected.');
    });
});
}

在线 process.send({ socket: socket}); 节点 js 得到错误“TypeError:将循环结构转换为 JSON”

-我使用了一些模块来转换圆形对象但不工作。

-我尝试传递套接字 id,然后在主进程中,用这个 id 创建了新的套接字,但我不知道要使用它。

有没有可能将套接字从工作进程传递给主进程?

节点js版本:v5.5.0

4

2 回答 2

1

嗯,我认为您尝试做的事情是不可能的。当您创建一个集群时,这意味着您创建了只能通过管道进行对话的单独进程(master + workers)。

通过管道交谈意味着他们只能互相发送字符串。process.send尝试使用JSON.stringify将 Javascript 对象序列化为 JSON(-> 从中生成字符串) 。例如 JSON 不能有函数、圆圈等。我刚刚检查了socket对象,它非常复杂并且包含函数(例如socket.emit()),所以你不能只是序列化它并通过管道发送它。

也许你可以检查这个这个关于如何使用集群 WebSockets。

这似乎不是很微不足道。也许您可以将 CPU 密集型任务传递给一些工作进程(通过集群或只是自己产生它们),将结果发送回主控并让他与客户端进行所有通信?

于 2016-02-01T21:46:43.837 回答
-1

我了解您向集群中的所有节点工作进程广播的目的,尽管您不能像这样发送套接字组件,但有一种解决方法可以达到此目的。我将尝试用一个例子来解释:

第 1 步:当客户端操作需要广播时:

Child.js(已分叉的进程):

socket.on("BROADCAST_TO_ALL_WORKERS", function (data) 
{
    process.send({cmd : 'BROADCAST_TO_ALL_WORKERS', message :data.message});
}) 

第 2 步:在集群创建方面

Server.js(集群分叉发生的地方):

if (cluster.isMaster) {

  for (var i = 0; i < numCPUs; i++) {

    var worker = cluster.fork();

    worker.on('message', function (data) {
     if (data.cmd === "BROADCAST_TO_ALL_WORKERS") {
       console.log(server_debug_prefix() + "Server Broadcast To All, Message : " + data.message + " , Reload : " + data.reload + " Player Id : " + data.player_id);
        Object.keys(cluster.workers).forEach(function(id) {
            cluster.workers[id].send({cmd : "BROADCAST_TO_WORKER", message : data.message});
        });
      }
    });
  }

  cluster.on('exit', function (worker, code, signal) {
    var newWorker = cluster.fork();
    newWorker.on('message', function (data) {
      console.log(data);
      if (data.cmd === "BROADCAST_TO_ALL_WORKERS") {
        console.log(data.cmd,data);
        Object.keys(cluster.workers).forEach(function(id) {
            cluster.workers[id].send({cmd : "BROADCAST_TO_WORKER", message : data.message});
        });
      }
    });
  });
} 
else {
  //Node Js App Entry
  require("./Child.js");
}

第三步:在子进程中广播

-> 把它放在 Child.js 中的 io.on("connection") 之前

process.on("message", function(data){
    if(data.cmd === "BROADCAST_TO_WORKER"){



    io.sockets.emit("SERVER_MESSAGE", { message: data.message, reload: data.reload, player_id : data.player_id });
}
});

我希望它清楚。如果它令人困惑,请发表评论......我会尽力说清楚。

于 2017-08-19T10:27:45.337 回答