DutchKevv
DutchKevv

Reputation: 1699

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!

Upvotes: 3

Views: 6426

Answers (3)

Suhail Doshi
Suhail Doshi

Reputation: 776

I found some PRs that were merged to solve this but I couldn't find the code anymore in 9.x of node-ipc

I basically made my own handshake:

  • on ipc.connectTo(), send your ipc.config.id via '_handshake' event: ipc.emit('_handshake', {client_id: ip.config.id})
  • on the server, listen for the '_handshake' and store the sock you get via a {client_id: sock} mapping
  • Now you can send to that specific socket from the server because you saved it.

Upvotes: 1

Slbox
Slbox

Reputation: 13138

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'
  }
);

Upvotes: 1

Miles Grimes
Miles Grimes

Reputation: 442

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 :)

Upvotes: 2

Related Questions