Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I use a socket to have several processes communicate with a central process?

For my application, I need to have a central process responsible for interacting with many client processes. The client processes need a way to identify and communicate with the central process. Additionally, the central process may not be running, and the client process needs a way to identify that fact. This application will be running on a Unix-like system, so I'd thought about using named pipes sockets for the task. How would I, specifically, go about using named pipes sockets for this task (actual code would be greatly appreciated!)? If named pipes sockets are not ideal, are there better alternatives?

like image 339
Mike Avatar asked Sep 10 '25 05:09

Mike


1 Answers

Named pipes are not really ideal for this - they are best suited for single-reader, single-writer situations.

UNIX-domain sockets, however, are perfectly suited for it. They use the sockets API, with the endpoint name being a filesystem entry (as with a named pipe).


Here's a very simple example (you will of course want to add copious error checking!). First the server side:

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

#define SOCKNAME "/tmp/foo"

int main()
{
    int s1, s2;
    int i;
    struct sockaddr_un sa = { AF_UNIX, SOCKNAME };

    unlink(SOCKNAME);
    s1 = socket(AF_UNIX, SOCK_STREAM, 0);
    bind(s1, (struct sockaddr *)&sa, sizeof sa);
    listen(s1, 5);

    for (i = 0; i < 10; i++)
    {
        struct sockaddr_un sa_client;
        socklen_t sa_len = sizeof sa_client;
        FILE *f;

        s2 = accept(s1, (struct sockaddr *)&sa_client, &sa_len);
        f = fdopen(s2, "r+");
        fprintf(f, "Hello, you are client number %d\n", i + 1);
        fclose(f);
    }

    return 0;
}

Now the client side:

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

#define SOCKNAME "/tmp/foo"

int main()
{
    int s1;
    struct sockaddr_un sa = { AF_UNIX, SOCKNAME };
    FILE *f;
    char buffer[1024];

    s1 = socket(AF_UNIX, SOCK_STREAM, 0);
    connect(s1, (struct sockaddr *)&sa, sizeof sa);
    f = fdopen(s1, "r+");

    while (fgets(buffer, sizeof buffer, f) != NULL)
    {
        printf("Message received: %s", buffer);
    }

    fclose(f);

    return 0;
}

Note that you should actually create the socket under /var/run/yourappname rather than in /tmp.

man 7 unix is a good resource for further investigation.

like image 75
caf Avatar answered Sep 12 '25 18:09

caf