Socketpair program using Poll System Call

  • In this program, you are going to learn

  • How to create a socket ?

  • How to create a fork ?

  • How to send a data ?

  • How to recv a data?

Let us answer few basic questions in this socket

Why use socketpair in the program?

What parameters does socketpair take?

Why use AF_UNIX as the domain for socketpair?

What is the significance of SOCK_STREAM as the socket type?

Can socketpair be used for network communication?

Why is protocol often specified as 0 in the socketpair call?

What is the purpose of the sv array in the socketpair call?

How does socketpair handle errors during execution?

Can the created sockets be used for communication between unrelated processes?

Can the created sockets be passed between processes using fork?

How does socketpair differ from other socket creation functions like socket?

How is data sent from the parent to the child process?

How is data received by the child process?

Why is close called for each socket in both parent and child processes?

What is the purpose of the poll system call?

How does poll differ from poll in terms of usability?

What types of file descriptors can be monitored using poll?

How does poll handle a set of file descriptors with different states (e.g., reading, writing, exception)?

How do you handle errors when using the poll system call?

How does poll handle a set of file descriptors with different states (e.g., reading, writing, exception)?

How does poll Checking Ready File Descriptors?

What does it mean if poll returns 0?

https://www.plantuml.com/plantuml/svg/ZP9lQy8m48VVzrFSteo4TQDzwn0KsK3cTAW3OOZKzeB1s9HSxDW-_Qv_79jsiBvfhx_ckIUN3iWdpXyF9hZoEpmWK96aQ99jK0T1ZsowHryasedXu-PrEbw5i9YDdZQBvVnX-1n250ALyZxe5Jg3FYZhze9BhK3KR_eGIM1s3k83IGPGNJrHMft9r5X2GULRjEObJQ8oul9ELJ1EulLPW2NcdZXycKqcuscRlk-qGH3rJSHIWgPV_GfhZ6122748j_6fMsNPSbqBlcx1bz8ro65QYjehXErHANIyV_s9Leccb3oI4nuDiLHkMm3ccLRVZwtoQ3cVtAH_p2Mkvd96wVpcNqCWxjfC-uUxTmRpBlSBmqQ_y-WwdSZR8XZmAlwzlW0=
  • There are many functions used in socketpair. We can classify those functions based on functionalities.

    • Create Socket

    • Fork

    • Poll

    • Recv data_packet

    • Send data_packet

    • Close socket

  • socketpair creates a pair of connected sockets for local inter-process communication. For example,

sockfd = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
  • fork creates a child process, and both the parent and child processes can communicate through the socket pair. For example,

pid_t pid = fork();
  • poll() is used for monitoring multiple file descriptors to see if I/O is possible on any of them.

ret = poll(fds, 1, -1);
  • recv is used in network programming to receive data from a connected socket. For example,

ret = recv(sv[1], buffer, sizeof(buffer), 0);
  • send is used in network programming to send data over a connected socket. For example,

ret = send(sv[0], buffer, strlen(buffer), 0);
  • close is used to close the socket To free up system resources associated with the socket. For example,

(void)close(sv[0]);
(void)close(sv[1]);
  • See the full program below,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
#include <poll.h>

#define BUFFER_SIZE 1024

int sv[2];

static void sigint_handler(
int signo)
{
   (void)close(sv[0]);
   (void)close(sv[1]);
   sleep(2);
   (void)printf("Caught sigINT!\n");
   exit(EXIT_SUCCESS);
}

void register_signal_handler(
int signum,
void (*handler)(int))
{
  if (signal(signum, handler) == 
  SIG_ERR) {
     printf("Cannot handle signal\n");
     exit(EXIT_FAILURE);
  }
}

int main() 
{
  int sockfd;
  int ret;
  struct pollfd fds[1];
  char buffer[BUFFER_SIZE];

  register_signal_handler(SIGINT,
  sigint_handler);

  sockfd = socketpair(AF_UNIX, 
  SOCK_STREAM, 0, sv);
 
  if (sockfd < 0) {
    perror("socketpair");
    return -1;
  }

  printf("Socket pair created\n");

  pid_t pid = fork();

  if (pid == -1) {
    perror("fork");
    return -2;
  }

  if (pid == 0) {
    // Child process (Server)
    (void)close(sv[0]);

    fds[0].fd = sv[1];
    fds[0].events = POLLIN;

    while (1) {
      ret = poll(fds, 1, -1);      
      if (ret == -1) {
         perror("poll");
         break;
      }
      
      if (fds[0].revents & POLLIN) {
        ret = recv(sv[1], buffer, 
        sizeof(buffer), 0);

        if (ret < 0) {
          perror("recv");
          break;
        }

        buffer[ret] = '\0';
        printf("Received from server: %s\n", 
        buffer);
      }
    }

    (void)close(sv[1]);
  } else {
    // Parent process (Client)
    (void)close(sv[1]);

    while (1) {
      memset(buffer, 0, 
      sizeof(buffer));
      strncpy(buffer, "hello child", 
      strlen("hello child") + 1);
      buffer[strlen(buffer) + 1] = '\0';
      
      ret = send(sv[0], buffer, 
      strlen(buffer), 0);

      if (ret < 0) {
        perror("send");
        break;
      }
      printf("Sending client buffer = %s\n", 
      buffer);
      sleep(1);
    }
  }

  (void)close(sv[0]);
  (void)close(sv[1]);
  return 0;
}

 1$ gcc -o socketpair socketpair.c
 2
 3$ sudo ./socketpair
 4
 5Socket pair created
 6Sending client buffer = hello child
 7Received from server: hello child
 8Sending client buffer = hello child
 9Received from server: hello child
10Sending client buffer = hello child
11Received from server: hello child
12Sending client buffer = hello child
13Received from server: hello child
14Sending client buffer = hello child
15Received from server: hello child
16Sending client buffer = hello child
17Received from server: hello child
18Sending client buffer = hello child
19Received from server: hello child
20Sending client buffer = hello child
21Received from server: hello child
22Sending client buffer = hello child
23Received from server: hello child
24Sending client buffer = hello child
25Received from server: hello child
26^CCaught sigINT!
27Caught sigINT!

Socket API

Learning

socketpair

creates a pair of connected sockets for local inter-process communication.

fork

creates a child process, and both the parent and child processes can communicate through the socket pair.

poll

Monitor multiple file descriptors (usually sockets) for read, write, or error conditions.

recv

Receive data from a connected socket.

send

Send data over a connected socket.

See Also