UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

  • Index
  • » General
  • » Interprocess communication using UNIX Domian Socket ?

#1 2014-05-07 10:37 AM

Ramesh_P
Member
Registered: 2014-03-13
Posts: 3

Interprocess communication using UNIX Domian Socket ?

Hi ,

I have multiple process running on the system, so my requirement is to make communication between each other.

for example:

--------------------   <---------> process 1
|   MASTER process |   <---------> process 2
--------------------   <---------> process 3

process1,2,3 can communicate with Master process to get system information, request and response should happen through same socket.
note: process1, process2, process3 need not to talk to each other.

refereed : http://www.rainydayz.org/beej/bgipc/unixsock.html

please find attached code where both the process are connected to each other using unix domain socket, but when we send some msg from process1 to master , msg is not getting delivered.

any issue here ?
please provide me code where above thing can be achieved.

Master process (server side code)

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SOCK_PATH "echo_socket"

int main(void)
{
    int s, s2, t, len;
    struct sockaddr_un local, remote;
    char str[100];

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

    local.sun_family = AF_UNIX;
    strcpy(local.sun_path, SOCK_PATH);
    unlink(local.sun_path);
    len = strlen(local.sun_path) + sizeof(local.sun_family);
    if (bind(s, (struct sockaddr *)&local, len) == -1) {
        perror("bind");
        exit(1);
    }

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

    for(;;) {
        int done, n;
        printf("Waiting for a connection...\n");
        t = sizeof(remote);
        if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {
            perror("accept");
            exit(1);
        }

        printf("Connected.\n");

        done = 0;
        do {
            n = recv(s2, str, 100, 0);
            if (n <= 0) {
                if (n < 0) perror("recv");
                done = 1;
            }

            if (!done) 
                if (send(s2, str, n, 0) < 0) {
                    perror("send");
                    done = 1;
                }
        } while (!done);

        close(s2);
    }

    return 0;
}

process 1 (client side code)

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SOCK_PATH "echo_socket"

int main(void)
{
    int s, t, len;
    struct sockaddr_un remote;
    char str[100];

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

    printf("Trying to connect...\n");

    remote.sun_family = AF_UNIX;
    strcpy(remote.sun_path, SOCK_PATH);
    len = strlen(remote.sun_path) + sizeof(remote.sun_family);
    if (connect(s, (struct sockaddr *)&remote, len) == -1) {
        perror("connect");
        exit(1);
    }

    printf("Connected.\n");

    while(printf("> "), fgets(str, 100, stdin), !feof(stdin)) {
        if (send(s, str, strlen(str), 0) == -1) {
            perror("send");
            exit(1);
        }

        if ((t=recv(s, str, 100, 0)) > 0) {
            str[t] = '\0';
            printf("echo> %s", str);
        } else {
            if (t < 0) perror("recv");
            else printf("Server closed connection\n");
            exit(1);
        }
    }

    close(s);

    return 0;
}

Offline

#2 2014-05-07 01:03 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,829
Website

Re: Interprocess communication using UNIX Domian Socket ?

Are you saying that the connect() in the client and accept() in the server both happen successfully, but nothing is ever read by the server's recv(), or is it the client's recv() that never gets the reply?

I just tested your exact code, and as long as I run both client and server in the same directory, they seem to work fine...  If you run them in different directories, they won't work, because you use a relative path for the socket name, so it's always going to be taken relative to the current directory of the process...  You could solve that by using a full path like "/tmp/echo_socket" or something...

But, I spot a couple issues with your code, anyway...  Add <unistd.h> to your #includes, for the prototype of unlink() and close()...  In the client, you either want to make your buffer 101 bytes in size or pass in 99 to recv(), since you add a null terminator based on the return value from recv()...  As it is, the server could theoretically send you a full 100 byte message and you'd overflow your buffer by adding the null byte...  Of course, in practice with your code as-is this is impossible, since you would never send it a message larger than 99 bytes in the first place, due to the fgets() limiting things to that at most...  But, just as a proactive security measure, it's a good idea to be wary of such practices...  Also, you're assuming that every send() corresponds to a single recv() on the other end, and that's not necessarily the case...  It's much more likely to work that way with Unix domain sockets than with TCP over the Internet, but it's still theoretically possible for a single large send() to require multiple recv()'s to read in full, or for a single recv() to read messages from multiple send()'s, because you're dealing with a simple stream protocol...  If you want a discrete message protocol, use datagram sockets...  Or, do the work necessary for making them work over a stream protocol: either prefix them with a fixed-size header giving the full length to read (and then read that exact amount from the stream), or terminate them with some character or series of characters, and then keep reading until you spot that terminator (and no further)...  You already effectively have a terminator due to the way fgets() works: a newline character...  The trick is replacing the simple recv() with something that just reads until it sees that newline...  One simple approach is just read a single character at a time until the newline is seen, appending bytes to a buffer as you go...  Another is to use recv(MSG_PEEK) to search for the location of the newline in your receive buffer, and then do a plain flagless recv() to only read that much and no more...  Yet another is to have a buffering layer that just reads as much as it can, but only returns you the amount upto the newline, saving any extra for the start of the next message...  That latter behavior is essentially just what stdio does for you, so one solution is to just fdopen() the socket and use fgets() on it!

Offline

#3 2014-05-07 01:16 PM

Ramesh_P
Member
Registered: 2014-03-13
Posts: 3

Re: Interprocess communication using UNIX Domian Socket ?

Thanks for your quick reply, after changing path it started working. now i have couple of question:

1. what is difference between send , recv and write,read system calls,  i can replace with write and read system call in place of send and recv.
2. is it possible send structure type in write or read system call instead of buffer.

for example :
                   char buffer[300];
                    struct Msg xMsg;
                   .........
                   .........
                   write(connection_fd, buffer, nbytes);  is it possible to use like this write(connection_fd, &xMsg , nbytes) if not how we can achieve this ?
                   read(connection_fd, buffer, nbytes);


thanks.

Offline

#4 2014-05-07 08:18 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,829
Website

Re: Interprocess communication using UNIX Domian Socket ?

1. what is difference between send , recv and write,read system calls,  i can replace with write and read system call in place of send and recv.

On normal Unix-like systems, yes you can use read() and write() instead of recv() and send()...  They function exactly like the latter with 0 for flags...  That's really all they offer over regular read()/write(): the special behavior that can be specified via the flags...  (However, on abnormal systems like Windows, sockets are not regular file descriptors, and so read() and write() won't work, and you MUST use recv()/send()...)

2. is it possible send structure type in write or read system call instead of buffer.

Sure...  We've got a FAQ entry on that subject here...  But, that was assuming sending stuff across the Internet, where you need to be careful because the receiver may be running on a completely different hardware architecture and/or OS than the sender is, so just sending the raw struct is not a good idea in general...  However, over Unix domain sockets, you know both ends are on the same exact machine, so there's no problem with doing so!  The only thing to worry about is if the struct contains pointers...  Pointers from one app won't mean anything to another app, so you don't want to send those...  But, if there are no pointers, then yeah just pass a pointer to the struct to send()/write() and recv()/read() along with the sizeof() the struct as the length...  (But, remember what I said about stream sockets and not being able to assume a single write corresponds to a single read...)

Offline

#5 2014-05-09 08:05 AM

Ramesh_P
Member
Registered: 2014-03-13
Posts: 3

Re: Interprocess communication using UNIX Domian Socket ?

thank q for your answer it helped me lot :)

Offline

  • Index
  • » General
  • » Interprocess communication using UNIX Domian Socket ?

Board footer

Powered by FluxBB