Thursday, January 10, 2013

Unix Domain Socket with Abstract Socket Address


The socket address is abstract when sun_path[0] is a null byte ('\0'). The rest of sun_path is used to name the socket in the abstract namespace which is independent of the file system. This feature is only supported in Linux and it is not portable.

With the abstract socket address, you don't need to maintain the socket file (e.g. unlink) in the file system. And there is no file permissions control over it.

Example of using the sockets:

server.cpp

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

int main(void)
{
    int socket_fd;
    struct sockaddr_un server_address, client_address;
    int bytes_received, bytes_sent, integer_buffer;
    socklen_t address_length = sizeof(struct sockaddr_un);

    if ((socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
    {
        perror("server: socket");
        return -1;
    }
   
    memset(&server_address, 0, sizeof(server_address));
    server_address.sun_family = AF_UNIX;
    strcpy(server_address.sun_path, "#UdsServer");
    server_address.sun_path[0] = 0;
   
    if (bind(socket_fd,
             (const struct sockaddr *) &server_address,
             address_length) < 0)
    {
        close(socket_fd);
        perror("server: bind");
        return -1;
    }

    for (;;)
    {
        bytes_received = recvfrom(socket_fd,
                                  &integer_buffer,
                                  sizeof(integer_buffer),
                                  0,
                                  (struct sockaddr *) &client_address,
                                  &address_length);

        if(bytes_received != sizeof(integer_buffer))
        {
            printf("Error: recvfrom - %d.\n", bytes_received);
        } else {
            printf("received: %d.\n", integer_buffer);

            integer_buffer += 10;

            bytes_sent = sendto(socket_fd,
                                &integer_buffer,
                                sizeof(integer_buffer),
                                0,
                                (struct sockaddr *) &client_address,
                                address_length);
        }
    }

    close(socket_fd);

    return 0;
}


client.cpp

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

int main(void)
{
    int socket_fd;
    struct sockaddr_un server_address, client_address;
    int bytes_received, bytes_sent, integer_buffer;
    socklen_t address_length = sizeof(struct sockaddr_un);

    if((socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
    {
        perror("client: socket");
        return -1;
    }
         
    memset(&client_address, 0, sizeof(client_address));
    client_address.sun_family = AF_UNIX;
    strcpy(client_address.sun_path, "#UdsClient");
    client_address.sun_path[0] = 0;

    if(bind(socket_fd,
            (const struct sockaddr *) &client_address,
            address_length) < 0)
    {
        perror("client: bind");
        return -1;
    }

    memset(&server_address, 0, sizeof(server_address));
    server_address.sun_family = AF_UNIX;
    strcpy(server_address.sun_path, "#UdsServer");
    server_address.sun_path[0] = 0;

    integer_buffer = 1;

    for (;;)
    {
       bytes_sent = sendto(socket_fd,
                           &integer_buffer,
                           sizeof(integer_buffer),
                           0,
                           (struct sockaddr *) &server_address,
                           address_length);

       bytes_received = recvfrom(socket_fd,
                                 &integer_buffer,
                                 sizeof(integer_buffer),
                                 0,
                                 (struct sockaddr *) &server_address,
                                 &address_length);

       if (bytes_received != sizeof(integer_buffer))
       {
           printf("Error: recvfrom - %d.\n", bytes_received);
           return -1;
       }

       printf("received: %d\n", integer_buffer);

       integer_buffer += 1;

       sleep(10);
    }

    close(socket_fd);

    return 0;
}


Run them, then run the command
netstat -ax | grep DGRAM
and you can see how the sockets look like.

unix  2      [ ]         DGRAM                    9911     @UdsClient
unix  2      [ ]         DGRAM                    9888     @UdsServer

No comments:

 
Get This <