Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node-IPC send message from server to client

When using node-ipc to communicate between NodeJS processes over IPC, it seems pretty simple to start a server and listen for connections, or create a client and connect to the server.

But there is something that doesn't seem all that simple:

How can the server push a message to a client?

The manual says,

On the client, listening to the server for a message:

ipc.connectTo('world', function(){
        ipc.of.world.on('hello', function(data){
                console.log(data);
            }
        )
    }
);

Pretty straightforward... But:

On the server, sending a message

// Start server
ipc.serve(function(){

    // Listen for connecting clients
    ipc.server.on('connect', socket => {
        // From here I can do ipc.server.emit(socket, 'message', {});
        // But I still do not know the ID of the client that just connected
        // There could be 10 child processes connecting, I do not know which client this is
    });
});

So lets say I setup the server as the given example above, and the client connected.. Than later on in a different timeFrame, On the server side, you would expect this to be the way to send a message to the client:

ipc.server.of[TheClientIdThatJustConnected].emit('myMessage')

But this does not work, as ipc.server.of is always an empty object and I still do not know the socket client IDs..

So the only way I can think of, is to start EVERY process as both a server and a client... Or after the client connected, I send an '_identification' event with a hardcoded ID and store that sockets in a separate object, but that doesn't make any sense, because the socket is already given in the on('connect') function of the ipc.serve()...

So, how does a node-ipc server send a message to a connected client?

Thanks!

like image 561
DutchKevv Avatar asked Jun 22 '26 02:06

DutchKevv


2 Answers

Having reviewed the docs and dug into the source, I think I can conclude there isn't a way to accomplish exactly what you're looking for. The ids of the sockets simply aren't exposed, though you can see the server maintains the information internally here and exposes it on the socket.disconnected event.

There are two solutions from what I can see, both requiring legwork on your end:

  1. Use ipc.server.broadcast to send messages to all of your clients. Along with the payload you want to transfer, you would include some sort of identifier. Clients then would do something with messages identified for them, and otherwise disregard the payload.

  2. Put the burden on the client to request a message from the server with ipc.of.world.emit(). This could be an "effectively-sync" operation in which the server responds immediately, but this model works in an async situation as well, with clients identifying their requests and the server responding when it has a result for the client's request.

Of course the "slightly more drastic" solution is always to fork node-ipc and make it work for your use case :)

like image 167
Miles Grimes Avatar answered Jun 24 '26 22:06

Miles Grimes


From the server side you can do something like this, assuming you only have one socket. You can adapt this to manage multiple sockets though too.

 
//  Define your server

let mySocket; 
ipc.serve(
  () => {
    ipc.server.on(
      'app.message',
      (data, socket) => {
        mySocket = socket;
        ipc.server.emit(
          socket,
          'app.message',
          {
            id: ipc.config.id,
            message: data.message
          }
        );
      }
    );
  }
);

ipc.server.start();


//  Emit a message to that socket later
ipc.server.emit(
  mySocket,
  'app.message',
  {
    id: ipc.config.id,
    message: 'Server emitted message'
  }
);
like image 45
Slbox Avatar answered Jun 25 '26 00:06

Slbox