
Creating client-server programs in C++ helps in understanding network programming and communication between applications over a network. Here are five examples that demonstrate basic client-server interactions:
Example 1: Basic TCP Echo Server
Description: A simple server that listens for connections on a TCP port and echoes back any data it receives from the client.
Server Code:
#include <iostream> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #define PORT 8080 int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; // Creating socket file descriptor server_fd = socket(AF_INET, SOCK_STREAM, 0); setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // Assigning IP and Port address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // Binding bind(server_fd, (struct sockaddr *)&address, sizeof(address)); // Listening for connections listen(server_fd, 3); // Accepting a connection new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen); read(new_socket, buffer, 1024); send(new_socket, buffer, strlen(buffer), 0); close(new_socket); close(server_fd); return 0; }
Client Code:
#include <iostream> #include <cstring> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #define PORT 8080 int main() { int sock = 0; struct sockaddr_in serv_addr; char *hello = "Hello from client"; char buffer[1024] = {0}; // Creating socket sock = socket(AF_INET, SOCK_STREAM, 0); // Setting up the struct serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); // Convert IPv4 and IPv6 addresses from text to binary inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); // Connect to the server connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); // Send and then receive data send(sock, hello, strlen(hello), 0); read(sock, buffer, 1024); std::cout << buffer << std::endl; close(sock); return 0; }
Example 2: UDP Communication
Description: A basic UDP server-client model where the server sends a message and the client receives it.
Server Code:
#include <iostream> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #define PORT 8080 int main() { int sockfd; struct sockaddr_in servaddr, cliaddr; char buffer[1024] = "Hello UDP Client"; socklen_t len = sizeof(cliaddr); // Create socket file descriptor sockfd = socket(AF_INET, SOCK_DGRAM, 0); // Filling server information servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_port = htons(PORT); // Bind the socket bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); // Send a message to the client sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *) &cliaddr, len); close(sockfd); return 0; }
Client Code:
#include <iostream> #include <cstring> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #define PORT 8080 int main() { int sockfd; struct sockaddr_in servaddr; char buffer[1024] = {0}; // Create socket sockfd = socket(AF_INET, SOCK_DGRAM, 0); // Server info servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); // Receive message socklen_t len = sizeof(servaddr); recvfrom(sockfd, buffer, 1024, 0, (struct sockaddr*)&servaddr, &len); std::cout << "Message from server: " << buffer << std::endl; close(sockfd); return 0; }
Example 3: Multithreaded TCP Server
Description: A multithreaded TCP server that can handle multiple client connections simultaneously.
Server Code:
#include <iostream> #include <thread> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #define PORT 8080 void handle_client(int client_socket) { char buffer[1024] = {0}; read(client_socket, buffer, 1024); send(client_socket, buffer, strlen(buffer), 0); close(client_socket); } int main() { int server_fd, client_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); server_fd = socket(AF_INET, SOCK_STREAM, 0); setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); bind(server_fd, (struct sockaddr *)&address, sizeof(address)); listen(server_fd, 3); while ((client_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) >= 0) { std::thread(handle_client, client_socket).detach(); } close(server_fd); return 0; }
Example 4: HTTP-like Simple Web Server
Description: A simple HTTP-like web server that serves predefined messages.
Server Code:
#include <iostream> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #define PORT 8080 int main() { int server_fd, client_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[30000] = {0}; server_fd = socket(AF_INET, SOCK_STREAM, 0); setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); bind(server_fd, (struct sockaddr *)&address, sizeof(address)); listen(server_fd, 3); while ((client_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) >= 0) { read(client_socket, buffer, 30000); const char *response = "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 12\n\nHello world"; send(client_socket, response, strlen(response), 0); close(client_socket); } return 0; }
Example 5: File Transfer via TCP
Description: Server sends a file to the client over a TCP connection.
Server Code:
#include <iostream> #include <fstream> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #define PORT 8080 bool sendFile(int socket) { std::ifstream file("example.txt", std::ios::binary); if (!file.is_open()) return false; // Send file data to the socket char buffer[1024]; while (!file.eof()) { file.read(buffer, sizeof(buffer)); send(socket, buffer, file.gcount(), 0); } file.close(); return true; } int main() { int server_fd, client_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); server_fd = socket(AF_INET, SOCK_STREAM, 0); setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); bind(server_fd, (struct sockaddr *)&address, sizeof(address)); listen(server_fd, 3); while ((client_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) >= 0) { if (!sendFile(client_socket)) { std::cerr << "Failed to send file." << std::endl; } close(client_socket); } close(server_fd); return 0; }
In each example, you may need to add appropriate error handling to check the result of socket calls and ensure resources are managed correctly. The examples demonstrate typical use cases and provide a foundation on which more complex applications can be built.