41

I have 2 applications on the same system that I need to communicate back and forth. From my research I believe this is called Inter Process Communication and the use of socketpair() is the best method for my problem.

I am tearing my hair out (literally) trying to get started with creating sockets with socketpair() in C. From what I understand, sockets are a very complex topic and me being a novice C programmer is surely not helping the situation.

I googled for the last 48 hours, read tutorials, etc, but I still can't get it. I understand the concept, but the code is just too confusing. I've read this article a few times: http://beej.us/guide/bgnet/html/single/bgnet.html, but it's not simple enough.

Can someone provide some example (so simple a 5th grader could understand) or point me to a good tutorial?

Sandburg
  • 757
  • 15
  • 28
NASA Intern
  • 823
  • 3
  • 11
  • 19
  • 6
    Please don't literally tear your hair out. That sounds painful. The first question we need to answer is this: are the two programs connected by a common ancestor? That is, does one launch the other? Or are they launched by a third program that you have written? Or are they launched independently of each other? – Robᵩ Jul 12 '12 at 21:42
  • 1
    Dude, IPC is not about sockets. its a totally different thing. rather than following the link you have posted, you should follow this.....http://beej.us/guide/bgipc/output/html/multipage/unixsock.html#socketpair – Aftnix Jul 12 '12 at 21:44
  • 1
    The 2 programs are connected by a common ancestor. – NASA Intern Jul 12 '12 at 22:34
  • That example is great! just what I was looking for! – NASA Intern Jul 17 '12 at 00:28
  • 3
    @Aftnix I'm just guessing that you were looking for that 'kindness' food supplement the other day. The very article you link to has this tasty morsel third paragraph down: "you can immediately use these socket descriptors for interprocess communication.". That spells IPC in my acronym book. And hey, look at the "dude"s user name! Unless s/he is joking, s/he might actually *be* a rocket scientist, deserving a little more respect (IMHO, FWIW). – ack Feb 18 '15 at 15:04

4 Answers4

77

You can use socketpair only where you create both processes, like so:

  1. call socketpair - now you have two socket file descriptors (two ends of a single pipe)
    • nominate one end to be the parent and one to be the child end. It doesn't matter which, just make a choice and stick to it later
  2. call fork - now you have two processes
    1. if fork returned zero, you are the child. Close the parent file descriptor, keep the child descriptor, and use it as this process's end of the pipe
    2. if fork returned non-zero, you are the parent. Close the child file descriptor, keep the parent one and use it as your end of the pipe
  3. you now have two processes, each has one file descriptor representing different ends of the same pipe. Note that both processes are running the same program, but they followed a different branch after calling fork. If parent calls write on its socket, child will be able to read that data from its socket, and vice-versa

Here is a straight translation into code:

void child(int socket) {
    const char hello[] = "hello parent, I am child";
    write(socket, hello, sizeof(hello)); /* NB. this includes nul */
    /* go forth and do childish things with this end of the pipe */
}

void parent(int socket) {
    /* do parental things with this end, like reading the child's message */
    char buf[1024];
    int n = read(socket, buf, sizeof(buf));
    printf("parent received '%.*s'\n", n, buf);
}

void socketfork() {
    int fd[2];
    static const int parentsocket = 0;
    static const int childsocket = 1;
    pid_t pid;

    /* 1. call socketpair ... */
    socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);

    /* 2. call fork ... */
    pid = fork();
    if (pid == 0) { /* 2.1 if fork returned zero, you are the child */
        close(fd[parentsocket]); /* Close the parent file descriptor */
        child(fd[childsocket]);
    } else { /* 2.2 ... you are the parent */
        close(fd[childsocket]); /* Close the child file descriptor */
        parent(fd[parentsocket]);
    }
    exit(0); /* do everything in the parent and child functions */
}

Please note that this is just sample code: I've left out all error-checking and a sensible stream protocol.


If you want two separate programs to communicate (eg. you have an executable called client, and one called server), you can't use this mechanism. Instead, you might:

  • use UNIX sockets (where an IPC pipe on one host is identified by a filename - this only works if client and server run on the same machine)
  • or use TCP/IP sockets (where an IP address and port identify the pipe, and the client and server can be on different machines)

If you don't specifically need sockets, and you're happy to require that client and server run on the same machine, you can also use shared memory, or message queues.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • They can be separate programs with a common ancestor. Just use `execl` (or other exec call) to run the program and it will inherit the socket. You just need a way to tell the program to use the socket that it inherited. – mark4o Jul 13 '12 at 03:01
  • true, but by the time you have that protocol, it isn't obviously much easier than just using UNIX sockets – Useless Jul 13 '12 at 09:36
  • 3
    Actually, you can pass a descriptor to an unrelated process: see sendmsg/recvmsg and "descriptor passing". It seems to be a popular search :) – fork0 Jul 13 '12 at 13:15
  • true, and it's a neat technique ... still, if OP can't follow existing sample code yet, I think that might be overkill :) – Useless Jul 13 '12 at 13:17
  • Why `Close the parent file descriptor` in child process and `Close the child file descriptor` in parent process? – Gary Gauh Jul 22 '13 at 06:25
  • It's a bad idea for the child to touch the parent's end of the pipe, and vice-versa, because there's a race condition between parent & child using the same socket. When each uses a _different_ socket, this is risk is avoided. If it isn't safe to use that fd, why keep it open? – Useless Jul 22 '13 at 11:04
  • Is is possible to use `socketpair()` once, create a child, once that child is done, create another child reusing the same pair of socket? (assuming you did not close the child socket in the parent, of course.) Note that I clearly know when the first child is dead as I receive the SIGCHLD signal. – Alexis Wilke Dec 03 '15 at 08:42
  • 1
    certainly: they're still just two ends of a pipe, and there's nothing special about one child process or another. – Useless Dec 03 '15 at 10:16
  • 1
    Why do you close the other end of the socket in the parent and child processes? Is that necessary? And can socketpair be used to communicate between two threads of the same process? – Guillaume Brunerie Jan 20 '17 at 23:05
9

socketpair creates an anonymous pair of sockets, usually unix/local sockets, which are only useful for communication between a parent and child process or in other cases where the processes that need to use them can inherit the file descriptors from a common ancestor.

If you're going to do communication between unrelated (in the sense of parentage) processes, you need to use socket, bind, and connect to create a listening socket in one process and create a client socket to connect to it in the other process.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 1
    weirdly, I find _socketpair sample code_ with a simple search for that phrase. I've provided some, but I'm surprised it's necessary – Useless Jul 13 '12 at 09:38
  • @Useless: That search sounds pretty useless since I was pointing out that `socketpair` is probably not the right tool for what OP wants to do. – R.. GitHub STOP HELPING ICE Jul 13 '12 at 14:31
1

For communicating between two processes, yes, Inter Process Communication or IPC is what you should look for. Sockets are just one of the methods for communicating and is useful if you have to implement one-to-many connection. Means, one server process which communicates with many client processes in a request-response fashion. As you are a newbie to IPC, it is understandable that socket addresses and the details involved might look difficult to grasp. (Though you will find them easy in due time :-))

For your problem, I suggest you use simpler IPC mechanisms like Pipe, FIFO, Message Queue. I am not sure how you came to the conclusion to use socketpair. Since you have not mentioned anything around the design or kind of IPC you need AND bassed on usage level I strongly recommend to look into Pipe or FIFO sample codes in some book or internet. They should look way easier to implement and work faster than sockets.

Groovy
  • 516
  • 5
  • 16
-4

Use TCP/IP. While there are other IPC mechanisms available (such as Unix domain sockets and SYSV IPC) you're better off with TCP/IP for many reasons. Here are some:

  1. There are lots of tutorials and other information on the web describing how to do TCP/IP
  2. Modern systems, and especially Linux and *BSD, impose no significant penalty for using TCP/IP compared to, say, Unix domain sockets or even SYSV IPC.
  3. There are a number of libraries and frameworks that you may be able to make use of for applications communicating over TCP/IP.

The only case where I would not use TCP/IP to communicate between two "programs" is for the case where they are really threads rather than separate programs.

James Youngman
  • 3,623
  • 2
  • 19
  • 21
  • 7
    I must disagree. Using TCP/IP for IPC between local processes has a lot of disadvantages, the biggest one being the fact that you have to concern yourself with security issues related to possible connections from remote hosts or even processes on the local host. Unix (local) sockets are much easier to secure, and much more appropriate if you'll be transmitting data in the host's binary format. You can also do useful things like passing file descriptors over them. – R.. GitHub STOP HELPING ICE Jul 12 '12 at 22:50
  • 5
    Unix sockets are definitely faster. Just consider that tcp has to go through all the loops of creating the IP packing and sending it over the loopback device, applying filter rules etc. – Per Johansson Jul 14 '12 at 19:37