UDP Broadcasting Implementation in C
The follownig example demonstraets how to create a UDP broadcast cliant in C using epoll for efficient I/O multiplexing. This client broadcasts messages to a specified network address and port, then listens for server responses.
Code Implementation
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#define MAX_BUFFER 1024
#define MAX_EPOLL_EVENTS 8
int main(int argc, char *argv[]) {
int target_port = 0;
char *network_addr = NULL;
int cmd_option;
// Parse command line arguments
while ((cmd_option = getopt(argc, argv, "p:a:")) != -1) {
switch (cmd_option) {
case 'p':
target_port = atoi(optarg);
break;
case 'a':
network_addr = optarg;
break;
default:
fprintf(stderr, "Usage: %s [-p port] [-a broadcast_address]\n", argv[0]);
exit(EXIT_FAILURE);
}
}
// Validate required parameters
if (target_port == 0 || network_addr == NULL) {
fprintf(stderr, "Both port and broadcast address must be specified\n");
exit(EXIT_FAILURE);
}
// Create UDP socket
int comm_socket;
if ((comm_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// Enable broadcast capability
int broadcast_flag = 1;
if (setsockopt(comm_socket, SOL_SOCKET, SO_BROADCAST, &broadcast_flag, sizeof(broadcast_flag)) < 0) {
perror("Broadcast option setting failed");
close(comm_socket);
exit(EXIT_FAILURE);
}
// Configure server address structure
struct sockaddr_in destination;
memset(&destination, 0, sizeof(destination));
destination.sin_family = AF_INET;
destination.sin_port = htons(target_port);
if (inet_pton(AF_INET, network_addr, &destination.sin_addr) <= 0) {
perror("Invalid network address");
close(comm_socket);
exit(EXIT_FAILURE);
}
// Initialize epoll instance
int epoll_descriptor = epoll_create1(0);
if (epoll_descriptor < 0) {
perror("Epoll creation failed");
close(comm_socket);
exit(EXIT_FAILURE);
}
// Add socket to epoll
struct epoll_event epoll_instance;
epoll_instance.events = EPOLLIN;
epoll_instance.data.fd = comm_socket;
if (epoll_ctl(epoll_descriptor, EPOLL_CTL_ADD, comm_socket, &epoll_instance) < 0) {
perror("Epoll control failed");
close(epoll_descriptor);
close(comm_socket);
exit(EXIT_FAILURE);
}
// Prepare for message sending
char message_buffer[MAX_BUFFER];
struct epoll_event active_events[MAX_EPOLL_EVENTS];
printf("Enter message to broadcast: ");
fflush(stdout);
if (fgets(message_buffer, MAX_BUFFER, stdin) == NULL) {
perror("Input error");
close(epoll_descriptor);
close(comm_socket);
exit(EXIT_FAILURE);
}
// Remove newline character if present
size_t message_length = strlen(message_buffer);
if (message_length > 0 && message_buffer[message_length - 1] == '\n') {
message_buffer[message_length - 1] = '\0';
message_length--;
}
// Broadcast the message
ssize_t bytes_sent = sendto(comm_socket, message_buffer, message_length, 0,
(struct sockaddr *)&destination, sizeof(destination));
if (bytes_sent < 0) {
perror("Message sending failed");
close(epoll_descriptor);
close(comm_socket);
exit(EXIT_FAILURE);
}
// Wait for server response
while (1) {
int event_count = epoll_wait(epoll_descriptor, active_events, MAX_EPOLL_EVENTS, -1);
if (event_count < 0) {
perror("Epoll wait error");
break;
}
for (int i = 0; i < event_count; i++) {
// Check for errors
if (active_events[i].events & (EPOLLERR | EPOLLHUP) ||
!(active_events[i].events & EPOLLIN)) {
fprintf(stderr, "Epoll error on socket\n");
break;
}
// Receive server response
ssize_t bytes_received = recvfrom(comm_socket, message_buffer, MAX_BUFFER, 0, NULL, NULL);
if (bytes_received < 0) {
perror("Message receiving failed");
break;
}
printf("Server response: %s\n", message_buffer);
break;
}
break; // Exit after receiving first response
}
// Cleanup resources
close(comm_socket);
close(epoll_descriptor);
return EXIT_SUCCESS;
}
Compilation and Execution
To compile this program, use the following command:
gcc -o broadcast_client broadcast_client.c
Execute the client with the target port and broadcast address:
./broadcast_client -p <port> -a <broadcast_address>
The client will prompt you to enter a message, broadcast it to the specified address, and display any response received from the server.