7

I want to communicate between NodeJS and a C program using node-ipc, over a Unix socket, which according to that homepage is the fastest option. (They will be on the same machine). That package claims it could communicate with a C program. (I had to sanity check).

The problem is the examples don't give example C code, and I have next to no idea how I'd get them to talk.

Can anyone point me to an example of C code to match those client/server examples? For example, how would I adapt this tutorial on working with unix pipes in C (Assuming I'm not completely off track?! Maybe it's "domain sockets" that I want instead?) None of this is making any sense to me, I'm missing something crucial.

Jodes
  • 14,118
  • 26
  • 97
  • 156
  • Are you trying to communicate the programs in both directions? Is this a commercial project? Would you pay for help? – Iharob Al Asimi Oct 03 '16 at 23:42
  • Yes, both directions. Paying for help isn't really an option, I just need a nudge in the right direction. I was going to use ZeroMQ but it seems like total overkill – Jodes Oct 04 '16 at 00:02
  • 1
    If it's on a POSIX system, it's a very simple task in fact. Sadly, I can't help you for free, or answering here since I consider that you need more than simple help. Unix Domain Sockets is the way to go, and I am sure if you google it right you will find plenty of examples with c code included. And it's a very simple thing in fact, just like a regular socket but with a different address and type. – Iharob Al Asimi Oct 04 '16 at 00:06
  • C has no significant here. You just need a language that can make system calls. If you're speaking over the network, it really doesn't matter what language you use. – Ryan Oct 04 '16 at 01:12
  • I would like to request more information about this, are you able/willing to share your project so I can learn more? – Jonathan Jun 06 '19 at 22:22

2 Answers2

17

I got it to work in the end with the code below. You can have it for free!

server.c

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>

char *socket_path = "/tmp/icp-test";

int main(int argc, char *argv[]) {
  struct sockaddr_un addr;
  char buf[100];
  int fd,cl,rc;

  if (argc > 1) socket_path=argv[1];

  if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
    perror("socket error");
    exit(-1);
  }

  memset(&addr, 0, sizeof(addr));
  addr.sun_family = AF_UNIX;
  if (*socket_path == '\0') {
    *addr.sun_path = '\0';
    strncpy(addr.sun_path+1, socket_path+1, sizeof(addr.sun_path)-2);
  } else {
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
    unlink(socket_path);
  }

  if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
    perror("bind error");
    exit(-1);
  }

  if (listen(fd, 5) == -1) {
    perror("listen error");
    exit(-1);
  }

  while (1) {
    if ( (cl = accept(fd, NULL, NULL)) == -1) {
      perror("accept error");
      continue;
    }

    while ( (rc=read(cl,buf,sizeof(buf))) > 0) {
      printf("read %u bytes: %.*s\n", rc, rc, buf);
    }
    if (rc == -1) {
      perror("read");
      exit(-1);
    }
    else if (rc == 0) {
      printf("EOF\n");
      close(cl);
    }
  }
  return 0;
}

client.js:

 var ipc=require('node-ipc');

var socketId = 'icp-test';
ipc.config.id   = 'hello';
ipc.config.socketRoot = '/tmp/';
ipc.config.appspace = '';

ipc.config.retry= 1500;
ipc.connectTo(
  socketId,
  function(){
    ipc.of[socketId].on(
      'connect',
      function(){
        console.log("Connected!!");
        ipc.log('## connected to world ##'.rainbow, ipc.config.delay);
        ipc.of[socketId].emit(
          'message',  //any event or message type your server listens for
          'hello'
        )
      }
    );
    ipc.of[socketId].on(
      'disconnect',
      function(){
        console.log("Disconnected!!");
        ipc.log('disconnected from world'.notice);
      }
    );
    ipc.of[socketId].on(
      'message',  //any event or message type your server listens for
      function(data){
        console.log("Got a message!!");
        ipc.log('got a message from world : '.debug, data);
      }
    );
  }
);

On a side note, I've realised that if you just want to do communicate between NodeJS via unix sockets with C, NodeJS actually comes with a module that does that already. Which as it turns out, is what node-ipc uses under the hood. So it might be easier just to use NodeJS's net package instead. This previous question points out how to do IPC in NodeJS. Just combine that with the above C code.

Community
  • 1
  • 1
Jodes
  • 14,118
  • 26
  • 97
  • 156
  • ``#include `` to squelch some warnings – kmiklas May 30 '17 at 21:12
  • @Jodes - this is really helpful! How did you achieve the two way communication? How do you pass data from the c server to the client? Also, my goal is to use express on the client so that it will receive requests and at some point to pass some work to the c server. Do you have any idea if the requests will be namespaced or do I need threads? – Stavros Zavrakas Dec 21 '17 at 11:25
  • @Jodes I have asked a question to clarify passing data in the reverse direction: https://stackoverflow.com/questions/52755754/communicating-between-c-and-nodejs-using-node-ipc-and-unix-sockets – Nicholas Hamilton Oct 11 '18 at 08:39
4

I think that you should be looking for C unix domain sockets, not pipes. Pipes are different. Look for some C code examples on Google with unix domain sockets, try a few out, get that working, then go back to the node-ipc stuff.

I took the node-ipc and node.js tags off because Node isn't relevant if you are trying to figure out the C side first.

Jason Livesay
  • 6,317
  • 3
  • 25
  • 31