Linux Socket Programming for Client-Server Communication
TCP Server Implementation
This example demonstrates a TCP echo server using epoll for efficient I/O multiplexing:
#include <sys/epoll.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_EVENTS 20
#define BUFFER_CAPACITY 4096
int create_listening_socket(int port_number, const char* interface_addr) {
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
struct sockaddr_in addr_config;
memset(&addr_config, 0, sizeof(addr_config));
addr_config.sin_family = AF_INET;
addr_config.sin_port = htons(port_number);
if (interface_addr) {
inet_pton(AF_INET, interface_addr, &addr_config.sin_addr);
} else {
addr_config.sin_addr.s_addr = INADDR_ANY;
}
if (bind(fd, (struct sockaddr*)&addr_config, sizeof(addr_config)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
if (listen(fd, 20) < 0) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
return fd;
}
int main(int argc, char** argv) {
int port = 8080;
const char* bind_addr = NULL;
// Command-line argument parsing omitted for brevity
int listen_sock = create_listening_socket(port, bind_addr);
int epoll_fd = epoll_create1(0);
struct epoll_event initial_event;
initial_event.events = EPOLLIN;
initial_event.data.fd = listen_sock;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, &initial_event);
struct epoll_event events[MAX_EVENTS];
char data_buffer[BUFFER_CAPACITY];
while (1) {
int ready_count = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
for (int i = 0; i < ready_count; i++) {
if (events[i].data.fd == listen_sock) {
struct sockaddr_in client_addr;
socklen_t addr_size = sizeof(client_addr);
int client_fd = accept(listen_sock, (struct sockaddr*)&client_addr, &addr_size);
struct epoll_event new_client;
new_client.events = EPOLLIN;
new_client.data.fd = client_fd;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &new_client);
} else {
ssize_t bytes_read = recv(events[i].data.fd, data_buffer, BUFFER_CAPACITY, 0);
if (bytes_read <= 0) {
close(events[i].data.fd);
continue;
}
send(events[i].data.fd, data_buffer, bytes_read, 0);
}
}
}
close(listen_sock);
return 0;
}
TCP Client Implementation
This TCP client establishes a connection and exchanges messages with a server:
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv) {
const char* server_ip = "127.0.0.1";
int port = 8080;
int connection_fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_config;
memset(&server_config, 0, sizeof(server_config));
server_config.sin_family = AF_INET;
server_config.sin_port = htons(port);
inet_pton(AF_INET, server_ip, &server_config.sin_addr);
connect(connection_fd, (struct sockaddr*)&server_config, sizeof(server_config));
const char* message = "Test message";
send(connection_fd, message, strlen(message), 0);
char response[1024];
ssize_t bytes_received = recv(connection_fd, response, sizeof(response), 0);
response[bytes_received] = '\0';
printf("Server response: %s\n", response);
close(connection_fd);
return 0;
}
UDP Server Implementation
UDP echo server implementation using datagram sockets:
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in server_config;
memset(&server_config, 0, sizeof(server_config));
server_config.sin_family = AF_INET;
server_config.sin_port = htons(8080);
server_config.sin_addr.s_addr = INADDR_ANY;
bind(socket_fd, (struct sockaddr*)&server_config, sizeof(server_config));
while (1) {
char datagram[1024];
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
ssize_t recv_size = recvfrom(socket_fd, datagram, sizeof(datagram), 0,
(struct sockaddr*)&client_addr, &client_len);
sendto(socket_fd, datagram, recv_size, 0,
(struct sockaddr*)&client_addr, client_len);
}
close(socket_fd);
return 0;
}
UDP Client Implementation
UDP client that sends messages and receives responses:
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in server_config;
memset(&server_config, 0, sizeof(server_config));
server_config.sin_family = AF_INET;
server_config.sin_port = htons(8080);
inet_pton(AF_INET, "127.0.0.1", &server_config.sin_addr);
const char* message = "UDP test";
sendto(socket_fd, message, strlen(message), 0,
(struct sockaddr*)&server_config, sizeof(server_config));
char response[1024];
recvfrom(socket_fd, response, sizeof(response), 0, NULL, NULL);
printf("Server reply: %s\n", response);
close(socket_fd);
return 0;
}