SocketPair Socket Connection

Till now we have seen examples wherein the socket connection is between two distinct processes. “socketpair API” socket connection allows a user to create a socket link between a Parent process and it’s child process.

Each process (ie. the parent and its child) gets two handles. The parent socket handle and the child socket handle. The parent process will close the child process socket handle and the child process will close the parent process socket handle. 

By doing so, there is a bi-directional pipe created with write and read operation available at each end. socketpair simplifies the connection establishment between the two processes as it is no longer required to perform bind/listen/accept or connect API operations.

The code for the socketpair API for a stream and datagram socket is provided below

Stream socketpair CodeDatagram socketpair code

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

/* Two socket ends – one for parent and
* the other for child */
int sockfd[2];

void send_data_to_parent(int sockfd) {
        char *string = “Hello parent process”;
        char buffer[100];

        snprintf(buffer, (strlen(string)+1), “%s”, string);
        write(sockfd, buffer, sizeof(buffer));
}

void send_data_to_child(int sockfd) {
        char *string = “Hello child process”;
        char buffer[100];

        snprintf(buffer, (strlen(string)+1), “%s”, string);
        write(sockfd, buffer, sizeof(buffer));
}

void read_data_from_parent(int sockfd) {
        char buffer[100];
        read(sockfd, buffer, sizeof(buffer));
        printf(“%s\n”, buffer);
}

void read_data_from_child(int sockfd) {
        char buffer[100];
        read(sockfd, buffer, sizeof(buffer));
        printf(“%s\n”, buffer);
}

int main () {
        int pid;
        int status;

        if (0 != (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd))) {
                printf(“socket_pair failed\n”);
                exit(0);
        }

        pid = fork();

        if (pid == -1) {
                printf(“fork failed – close the sockets\n”);
                close(sockfd[0]);
                close(sockfd[1]);
                exit(0);
        } else if (0 == pid) { /*child process – fork returns 0 in the child process*/
                /* close the socket connection for parent */
                close(sockfd[0]);
                send_data_to_parent(sockfd[1]);
                read_data_from_parent(sockfd[1]);
        } else { /*parent process – fork returns pid of child to parent*/
                /* close the socket connection for child */
                close(sockfd[1]);
                send_data_to_child(sockfd[0]);
                read_data_from_child(sockfd[0]);

                /* do not let Parent process die before child */
                waitpid(pid, &status, 0);

                if (WIFSIGNALED(status)) {
                        printf(“child process exited with error\n”);
                } else if (WEXITSTATUS(status)) {
                        printf(“child process exited normally\n”);
                }
        }

        if (sockfd[0] != -1)
                close(sockfd[0]);
        if (sockfd[1] != -1)
                close(sockfd[1]);
        return 0;
}

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

/* Two socket ends – one for parent and
* the other for child */
int sockfd[2];

void send_data_to_parent(int sockfd) {
        char *string = “Hello parent process”;
        char buffer[100];

        snprintf(buffer, (strlen(string)+1), “%s”, string);
        write(sockfd, buffer, sizeof(buffer));
}

void send_data_to_child(int sockfd) {
        char *string = “Hello child process”;
        char buffer[100];

        snprintf(buffer, (strlen(string)+1), “%s”, string);
        write(sockfd, buffer, sizeof(buffer));
}

void read_data_from_parent(int sockfd) {
        char buffer[100];
        read(sockfd, buffer, sizeof(buffer));
        printf(“%s\n”, buffer);
}

void read_data_from_child(int sockfd) {
        char buffer[100];
        read(sockfd, buffer, sizeof(buffer));
        printf(“%s\n”, buffer);
}

int main () {
        int pid;
        int status;

        if (0 != (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockfd))) {
                printf(“socket_pair failed\n”);
                exit(0);
        }

        pid = fork();

        if (pid == -1) {
                printf(“fork failed – close the sockets\n”);
                close(sockfd[0]);
                close(sockfd[1]);
                exit(0);
        } else if (0 == pid) { /*child process – fork returns 0 in the child process*/
                /* close the socket connection for parent */
                close(sockfd[0]);
                send_data_to_parent(sockfd[1]);
                read_data_from_parent(sockfd[1]);
                sockfd[0] = -1;
        } else { /*parent process – fork returns pid of child to parent*/
                /* close the socket connection for child */
               close(sockfd[1]);
               send_data_to_child(sockfd[0]);
               read_data_from_child(sockfd[0]);
               sockfd[1] = -1;
               /* do not let Parent process die before child */
              waitpid(pid, &status, 0);

              if (WIFSIGNALED(status)) {
                      printf(“child process exited with error\n”);
              } else if (WEXITSTATUS(status)) {
                      printf(“child process exited normally\n”);
              }
        }
        if (sockfd[0] != -1)
                close(sockfd[0]);
        if (sockfd[1] != -1)
                close(sockfd[1]);

        return 0;
}

Sequenced socket (SOCK_SEQPACKET) connection

Comments

  1. Pingback: Analyzing the AF_UNIX Abstract Namespace Datagram socket code example | Hitch Hiker's Guide to Learning

Leave a Reply

Your email address will not be published. Required fields are marked *