Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Đảo ngược chuỗi trong C/C++ với mô hình Client - Server

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

  1. Biên dịch Server: gcc Server.c -o server
  2. Chạy Server: ./server (Server sẽ chờ kết nối).
  3. Biên dịch Client: gcc Client.c -o client
  4. 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

Đảo ngược chuỗi trong C/C++ với mô hình Client - Server

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).