Bài viết này trình bày cách xây dựng một hệ thống Client - Server đơn giản sử dụng lập trình socket trong C. Client gửi một chuỗi đến Server, Server đảo ngược chuỗi đó và gửi kết quả trả về Client.
Yêu cầu
- Hệ điều hành Linux/Unix (sử dụng socket POSIX).
- Biên dịch với
gcc. - Cả Client và Server phải sử dụng cùng một số cổng (port).
Quy trình chạy
- Biên dịch Server:
gcc Server.c -o server - Chạy Server:
./server(Server sẽ chờ kết nối). - Biên dịch Client:
gcc Client.c -o client - Chạy Client:
./client, nhập chuỗi cần đảo ngược.
Mã nguồn Client (Client.c)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 4000
int main() {
struct sockaddr_in server_address;
int my_socket = 0, valread;
char str[100];
char buffer[1024] = {0};
printf("Nhap mot chuoi: ");
fgets(str, 100, stdin); // Đọc chuỗi bao gồm khoảng trắng
// Tạo socket
if ((my_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\nKhong the tao socket\n");
return -1;
}
memset(&server_address, '0', sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
// Chuyển đổi địa chỉ IP (127.0.0.1 - localhost)
if (inet_pton(AF_INET, "127.0.0.1", &server_address.sin_addr) <= 0) {
printf("\nDia chi khong hop le\n");
return -1;
}
// Kết nối đến Server
if (connect(my_socket, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) {
printf("\nKhong the ket noi den server\n");
return -1;
}
// Gửi chuỗi đến Server
send(my_socket, str, sizeof(str), 0);
// Nhận chuỗi đã đảo ngược từ Server
valread = read(my_socket, str, sizeof(str));
printf("Chuoi dao nguoc tu Server: %s\n", str);
close(my_socket);
return 0;
}
Mã nguồn Server (Server.c)
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 4000
// Hàm đảo ngược chuỗi tại chỗ (in-place) dùng XOR swap
char* strrev(char *str) {
if (!str || !*str) return str;
char *p1 = str, *p2 = str + strlen(str) - 1;
while (p2 > p1) {
*p1 ^= *p2;
*p2 ^= *p1;
*p1 ^= *p2;
++p1; --p2;
}
return str;
}
int main() {
int server_fd, new_socket, valread;
struct sockaddr_in address;
char str[100];
int addrlen = sizeof(address);
// Tạo socket
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Tao socket that bai");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY; // Lắng nghe trên tất cả interface
address.sin_port = htons(PORT);
// Gắn socket với cổng
if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
perror("Bind that bai");
exit(EXIT_FAILURE);
}
// Lắng nghe kết nối (hàng đợi tối đa 3)
if (listen(server_fd, 3) < 0) {
perror("Listen that bai");
exit(EXIT_FAILURE);
}
printf("Server dang cho ket noi tren cong %d...\n", PORT);
// Chấp nhận kết nối từ Client
if ((new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen)) < 0) {
perror("Accept that bai");
exit(EXIT_FAILURE);
}
// Đọc chuỗi từ Client
valread = read(new_socket, str, sizeof(str));
printf("Chuoi nhan duoc: %s\n", str);
// Đảo ngược chuỗi
strrev(str);
// Gửi kết quả trả về Client
send(new_socket, str, sizeof(str), 0);
printf("Da gui chuoi dao nguoc ve Client.\n");
close(new_socket);
close(server_fd);
return 0;
}
Kết quả mẫu

Giải thích: Server sử dụng INADDR_ANY để chấp nhận kết nối từ bất kỳ địa chỉ IP nào. Hàm strrev triển khai thuật toán hoán đổi XOR để đảo chuỗi mà không cần bộ nhớ đệm phụ. Đây là ví dụ cơ bản về giao tiếp TCP một chiều (request-response).