Unix Sockets

A simple client and server can be set-up with the following code.

C Server

This code has been modified using the example given in the Linux documentation.

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

int
main(int argc, char *argv[])
{
    struct sockaddr_un name;
    int down_flag = 0;
    int ret;
    int connection_socket;
    int data_socket;
    char buffer[BUFFER_SIZE];

    /* Create local socket. */

    connection_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
    if (connection_socket == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    /*
    * For portability clear the whole structure, since some
    * implementations have additional (nonstandard) fields in
    * the structure.
    */

    memset(&name, 0, sizeof(name));

    /* Bind socket to socket name. */

    name.sun_family = AF_UNIX;
    strncpy(name.sun_path, SOCKET_NAME, sizeof(name.sun_path) - 1);

    ret = bind(connection_socket, (const struct sockaddr *) &name,
                sizeof(name));
    if (ret == -1) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    /*
    * Prepare for accepting connections. The backlog size is set
    * to 20. So while one request is being processed other requests
    * can be waiting.
    */

    ret = listen(connection_socket, 20);
    if (ret == -1) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    /* This is the main loop for handling connections. */

    for (;;) {
        /* Ensure buffer is zero'd*/
        memset(buffer, 0, sizeof(buffer));

        /* Wait for incoming connection. */
        data_socket = accept(connection_socket, NULL, NULL);
        if (data_socket == -1) {
            perror("accept");
            exit(EXIT_FAILURE);
        }

        for (;;) {

            /* Wait for next data packet. */

            ret = read(data_socket, buffer, sizeof(buffer));
            if (ret == -1) {
                perror("read");
                exit(EXIT_FAILURE);
            }

            /* Ensure buffer is 0-terminated. */

            buffer[sizeof(buffer) - 1] = 0;

            /* Handle commands. */
            printf("%s\n", buffer);
            if (!strncmp(buffer, "SEND", sizeof(buffer))) {
                printf("Sending Data\n");
                break;
            }

            if(!strncmp(buffer, "DOWN", sizeof(buffer))){
                printf("Closing Program");
                down_flag = true;
                break;
            }
        }

        sprintf(buffer, "Hello World!\n");
        int buf_size = strlen(buffer);

        /* Send Sizeof Buffer */
        printf("Sending buffer of size: %d\n", buf_size);

        ret = write(data_socket, &buf_size, sizeof(buf_size));
        if (ret == -1) {
            perror("write");
            exit(EXIT_FAILURE);
        }

        /*Send Buffer */
        printf("Sending contents of Buffer\n");
        ret = write(data_socket, buffer, sizeof(buffer));
        if (ret == -1) {
            perror("write");
            exit(EXIT_FAILURE);
        }

        /* Close socket. */

        close(data_socket);

        /* Quit on DOWN command. */

        if (down_flag) {
            break;
        }
    }

    close(connection_socket);

    /* Unlink the socket. */

    unlink(SOCKET_NAME);

    exit(EXIT_SUCCESS);
}

The connection.h file:

#define SOCKET_NAME "/tmp/9Lq7BNBnBycd6nxy.socket"
#define BUFFER_SIZE 1500

Python Client

This client code requests the buffer from the server.

import socket
import sys

ADDRESS = "/tmp/9Lq7BNBnBycd6nxy.socket"

sock = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)

sock.connect(ADDRESS)
sock.send(b"SEND")

len_data_bytes = sock.recv(4)
len_data = int.from_bytes(len_data_bytes, sys.byteorder, signed=True)
print(len_data)

data = sock.recv(len_data)
print(data.decode())