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

Xây dựng một máy chủ socket đa tiến trình trong C bằng Fork

Xây dựng một máy chủ socket đa tiến trình trong C bằng Fork

Một máy chủ socket đa xử lý có phân nhánh trong C cho phép chúng tôi xử lý đồng thời nhiều kết nối máy khách. Bằng cách sử dụng lệnh gọi hệ thống fork, máy chủ có thể tạo các tiến trình con cho từng máy khách được kết nối để đảm bảo các kênh liên lạc độc lập. Cách tiếp cận này cho phép giao tiếp đồng thời với nhiều khách hàng.

Hãy để chúng tôi thảo luận về cách triển khai một máy chủ socket đa xử lý có phân nhánh trong C. Chúng tôi sẽ giải thích về các ví dụ lập trình của chương trình phía máy chủ và chương trình phía máy khách mà nhờ đó chúng ta có thể đạt được một máy chủ socket đa xử lý có phân nhánh trong C.

Lệnh gọi hệ thống Fork là gì?

Khi một lệnh gọi hệ thống tạo một bản sao của một quy trình hiện có, nó được gọi là lệnh gọi hệ thống “fork()”. Về cơ bản, nó chia chương trình đang chạy thành hai tiến trình riêng biệt được gọi là tiến trình mẹ và tiến trình con. Tất cả các tham số đều giống nhau đối với các tiến trình con và tiến trình cha, ngoại trừ việc chúng có các PID khác nhau. Cuộc gọi hệ thống này trả về kết quả sau:

  1. PID của tiến trình con gửi tới tiến trình cha
  2. Không (0) cho đứa trẻ

Ví dụ lập trình 1:Chương trình phía máy chủ

#include
#include
#include
#include
#include
#include
#include
#include

#define PORT 8888

int chính ()
{
    int serSoc, cliSoc;
    struct sockaddr_in serverAddr, clientAddr;
    socklen_t addrSize =sizeof (clientAddr);
    bộ đệm char [1024];
    int clientCount =0;

    // Tạo ổ cắm máy chủ
    serSoc =socket(AF_INET, SOCK_STREAM, 0);
    if (serSoc <0) {
        perror ("Lỗi khi tạo socket");
        thoát (1);
   

    printf ("Đã tạo ổ cắm máy chủ.\n");

    // chúng ta hãy đặt địa chỉ máy chủ
    serverAddr.sin_family =AF_INET;
    serverAddr.sin_port =htons (PORT);
    serverAddr.sin_addr.s_addr =INADDR_ANY;

   
    if (bind(serSoc, (struct sockaddr*) &serverAddr, sizeof (serverAddr)) <0) {
        perror ("Lỗi khi liên kết");
        thoát (1);
   

    // Bắt đầu lắng nghe các kết nối đến
    if (nghe (serSoc, 5) ==0) {
        printf ("Đang nghe kết nối...\n");
    } khác {
        perror ("Lỗi khi nghe");
        thoát (1);
   

    trong khi (1) {
        // Hãy để chúng tôi  Chấp nhận kết nối  máy khách
        cliSoc  =chấp nhận (serSoc, (struct sockaddr* )&clientAddr, &addrSize);
        if (cliSoc  <0) {
            perror("Lỗi chấp nhận kết nối");
            thoát (1);
       

        // Tăng số lượng client và hiển thị thông tin client

        clientCount++;
        printf("Kết nối được chấp nhận từ Máy khách %d:%s:%d\n", clientCount, inet_ntoa (clientAddr.sin_addr), ntohs (clientAddr.sin_port));
        printf ("Tổng số máy khách được kết nối:%d\n", clientCount);

       
        pid_t pid =ngã ba ();

        nếu (pid ==0) {
            // Tiến trình con

           
            đóng (serSoc);

            // Nhận tin nhắn từ client
            trong khi (1) {
                bộ nhớ (bộ đệm, 0, sizeof(bộ đệm));
                if (recv (cliSoc , buffer, sizeof (buffer), 0) <0) {
                    perror ("Lỗi khi nhận dữ liệu");
                    thoát (1);
               

                printf ("Dữ liệu đã nhận từ Máy khách %d:%s\n", clientCount, bộ đệm);

                // Gửi lại tin nhắn đã nhận cho client
                if (send (cliSoc , buffer, strlen (buffer), 0)  0) {
            // Tiến trình cha

           
            đóng(cliSoc );
        } khác {
            perror ("Lỗi khi phân nhánh");
            thoát (1);
        }
   

    // Đóng socket máy chủ
    đóng (serSoc);

    trả về 0;

PrVí dụ về lập biểu đồ 2:Chương trình phía khách hàng

#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 8888
#define SERVER_IP "127.0.0.1"

int chính ()
{
    int cliSoc;
    struct sockaddr_in serverAddr;
    bộ đệm char [1024];
    // Tạo ổ cắm máy khách
    cliSoc  =ổ cắm (AF_INET, SOCK_STREAM, 0);
    if (cliSoc  <0) {
        perror ("Lỗi khi tạo socket");
        thoát (1);
   

    printf("Đã tạo socket %d client.\n", getpid ());

    // Đặt tham số địa chỉ máy chủ
    serverAddr.sin_family =AF_INET;
    serverAddr.sin_port =htons (PORT);
    serverAddr.sin_addr.s_addr =inet_addr (SERVER_IP);
    // Kết nối với máy chủ
    if (kết nối (cliSoc , (struct sockaddr*) &serverAddr, sizeof (serverAddr)) <0) {
        perror("Lỗi kết nối tới máy chủ");
        thoát (1);
   

    printf ("Đã kết nối với máy chủ.\n");
    trong khi (1) {
        // Đọc đầu vào từ người dùng
        printf ("Khách hàng %d - Nhập tin nhắn:", getpid ());
        fgets (bộ đệm, sizeof(buffer), stdin);

       
        if (send (cliSoc , buffer, strlen (buffer), 0) <0) {
            perror ("Lỗi khi gửi dữ liệu");
            thoát (1);

        }
        // Nhận phản hồi từ máy chủ
        bộ nhớ (bộ đệm, 0, sizeof(bộ đệm));
        if (recv (cliSoc , buffer, sizeof (buffer), 0) <0) {
            perror ("Lỗi khi nhận dữ liệu");
            thoát (1);
        }
        printf ("Máy khách %d - Phản hồi của máy chủ:%s\n", getpid (), bộ đệm);
   

    // Đóng socket máy khách
    đóng (cliSoc );
    trả về 0;

Đầu ra:

**Biên dịch chương trình máy chủ**
$ gcc ser.c -o ser
$ ./ser
Đã tạo ổ cắm máy chủ.
Lắng nghe kết nối...
Đã tạo ổ cắm máy chủ.
Lắng nghe kết nối...
Kết nối được chấp nhận từ Client 1:127.0.0.1:59074
Tổng số khách hàng đã kết nối:1
Đã nhận data từ Client 1:hii admin
Kết nối được chấp nhận từ Máy khách 2:127.0.0.1:40192
Tổng số khách hàng đã kết nối:2
Đã nhận được dữ liệu từ Client 2:xin chào mọi người
**Biên dịch chương trình Client 1**
$ gcc cel.c -o cel
$ ./cel
Ổ cắm máy khách 4007 đã được tạo.
Đã kết nối với máy chủ.
Client 4007 - Nhập tin nhắn:hii admin

**Biên dịch chương trình client 2**
$ gcc cel.c -o cel
$ ./cel
Đã tạo ổ cắm máy khách 4024.
Đã kết nối với máy chủ.
Client 4024 - Nhập tin nhắn:xin chào mọi người

Giải thích:

Trong ví dụ lập trình này, chúng tôi đã giải thích cách triển khai máy chủ socket đa xử lý với phân nhánh trong C. Ở đây, trong chương trình phía máy chủ, chúng tôi tạo một socket máy chủ, liên kết nó với một địa chỉ và cổng cụ thể, đồng thời lắng nghe các kết nối đến. Khi một máy khách kết nối, một tiến trình con sẽ được tạo bằng cách sử dụng “fork()”. Điều này cho phép xử lý đồng thời nhiều khách hàng. Tiến trình con nhận tin nhắn từ máy khách và hiển thị dữ liệu kèm theo ID của máy khách. Máy chủ socket đa xử lý này cho phép chúng tôi liên lạc đồng thời với số lượng máy khách “n”.

Kết luận

Chúng ta đã thảo luận về việc triển khai một máy chủ socket đa xử lý với fork trong C. Sử dụng lệnh gọi hệ thống fork, điều này cho phép chúng ta xử lý đồng thời nhiều kết nối máy khách. Điều này cho phép giao tiếp đồng thời với nhiều khách hàng và xử lý hiệu quả các yêu cầu của khách hàng.

Giới thiệu về tác giả

Xây dựng một máy chủ socket đa tiến trình trong C bằng Fork

Bamdeb Ghosh

Bamdeb Ghosh đang có kinh nghiệm thực tế trong lĩnh vực Mạng không dây. Anh ấy là chuyên gia về phân tích chụp Wireshark trên Mạng không dây hoặc Mạng có dây cùng với kiến thức về các lệnh Android, Bluetooth, Linux và python. Theo dõi trang web của anh ấy:wifisharks.com