Communicating between C and NodeJS using node-ipc and unix sockets

1.1k Views Asked by At

This question follows on from the following:

Communicating between NodeJS and C using node-ipc and unix sockets

In regards to the accepted solution (https://stackoverflow.com/a/39848936/1834057), I was wondering if someone might be able to clarify exactly how to send data from C to Node.js. The solution demonstrates sending data from Node.js to C, but not in reverse. I have an application that requires two-way communications, so the missing component is critical for me.

My understanding of unix sockets that one of either write, send or sendmsg should be able to do the job, however, I am not having any luck. If this understanding is incorrect, please advise.

In order to get a trivial example running, lets say when a message is read in the C code, lets send back a message and try to trigger the ipc.of[socketId].on('message',...) event on the node server.

Which means I am trying to turn this:

while ( (rc=read(cl,buf,sizeof(buf))) > 0) {
      printf("read %u bytes: %.*s\n", rc, rc, buf);
}

Into this:

while ( (rc=read(cl,buf,sizeof(buf)) ) > 0) {
  printf("read %u bytes: %.*s\n", rc, rc, buf);

  //Respond to the node server
  int n;
  char * msg = "{\"type\":\"message\",\"data\":\"hello response\"}\t";
  if((n = write(fd,msg,sizeof(msg))) < 0){
      printf("send failed\n");
  }else{
      printf("sent %d bytes\n", n);
  }
}

This would mean that the complete server.c code now becomes:

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <string.h> //Missing from original server.c

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

      //Respond to the node server
      int n;
      char * msg = "{\"type\":\"message\",\"data\":\"hello response\"}\t";
      if((n = write(fd,msg,sizeof(msg))) < 0){
          printf("send failed\n");
      }else{
          printf("sent %d bytes\n", n);
      }
    }

    if (rc == -1) {
      perror("read");
      exit(-1);
    }
    else if (rc == 0) {
      printf("EOF\n");
      close(cl);
    }
  }
  return 0;
}

Now unfortunately, the write message for me returns code -1, and is not received by the node.js server.

The client.js code remains unchanged, and is as provided in the original question.

Can someone please clarify what I am doing wrong?

1

There are 1 best solutions below

0
On

You have to change

char * msg = "{\"type\":\"message\",\"data\":\"hello response\"}\t";
if((n = write(fd,msg,sizeof(msg))) < 0){
    printf("send failed\n");
}else{
    printf("sent %d bytes\n", n);
}

to

char * msg = "{\"type\":\"message\",\"data\":\"hello response\"}\f";
if((n = write(cl,msg,strlen(msg))) < 0){
    printf("send failed\n");
}else{
    printf("sent %d bytes\n", n);
}

The library is waiting for \f at the end of the message :-)

hope the answer is not too late :-)