Welcome to a comprehensive guide on the poll() function in C programming! This function is a powerful tool for handling multiple events in a non-blocking manner, making it a valuable asset for developing efficient and responsive applications. Let's dive in and understand this fascinating concept together! 💡
poll() function? 📝The poll() function is part of the Advanced Linux Programming (ALP) library, which provides a more efficient alternative to the traditional Unix I/O functions like select() and pselect(). The primary advantage of poll() is that it allows for the handling of a large number of file descriptors more effectively, making it suitable for applications dealing with numerous network connections or I/O operations. 💡
poll() object 📝To work with the poll() function, we first need to create a struct pollfd object, which contains the necessary details about the file descriptor we want to monitor. Here's the structure definition:
struct pollfd {
int fd; /* File descriptor */
short events; /* Events to watch for */
short revents; /* Returned events */
};Let's break it down:
fd: This is the file descriptor of the entity we're interested in, such as a socket, pipe, or terminal.events: This field contains a bitmask specifying the events we're interested in being notified about, such as readability, writability, or exceptions.revents: This field contains a bitmask that gets set to the actual events that occurred on the file descriptor while the call to poll() was blocking.Let's put together a simple example to demonstrate the usage of the poll() function. We'll create a program that listens on a TCP socket and waits for incoming connections. As soon as a new connection is accepted, the program will start reading data from the client.
#include <stdio.h>
#include <sys/socket.h>
#include <poll.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0};
// Create a socket
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// Set options on the socket
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
// Configure the address for the server
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
// Bind the socket to the address
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// Listen for incoming connections
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// Create the polling array
struct pollfd poll_fds[5];
poll_fds[0].fd = server_fd;
poll_fds[0].events = POLLIN;
// Accept incoming connections
while (1) {
int poll_result = poll(poll_fds, 1, -1);
if (poll_result < 0) {
perror("poll failed");
break;
}
if (poll_fds[0].revents & POLLIN) {
// Accept a new connection
if ((new_socket = accept(server_fd, (struct sockaddr *)NULL, (socklen_t *)NULL)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
// Add the new socket to the polling array
poll_fds[1].fd = new_socket;
poll_fds[1].events = POLLIN;
}
// Attempt to read data from the new connection
if (poll_fds[1].revents & POLLIN) {
read(poll_fds[1].fd, buffer, BUFFER_SIZE);
printf("Received data: %s\n", buffer);
}
}
return 0;
}This example creates a server that listens for incoming connections on port 8080. Once a new connection is established, it adds the new file descriptor to the polling array and starts monitoring it for read events. As soon as data arrives, it gets printed to the console.
Which header file must be included to use the `poll()` function in C?
What is the role of the `events` field in the `struct pollfd` object?