Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม C

สร้างเซิร์ฟเวอร์ซ็อกเก็ตหลายกระบวนการใน C โดยใช้ Fork

สร้างเซิร์ฟเวอร์ซ็อกเก็ตหลายกระบวนการใน C โดยใช้ Fork

เซิร์ฟเวอร์ซ็อกเก็ตการประมวลผลหลายตัวที่มีทางแยกในภาษา C ช่วยให้เราสามารถจัดการการเชื่อมต่อไคลเอนต์หลายตัวพร้อมกันได้ ด้วยการใช้การเรียกระบบทางแยก เซิร์ฟเวอร์สามารถสร้างกระบวนการลูกสำหรับไคลเอนต์ที่เชื่อมต่อแต่ละเครื่อง ซึ่งช่วยให้มั่นใจได้ถึงช่องทางการสื่อสารที่เป็นอิสระ แนวทางนี้ช่วยให้สามารถสื่อสารพร้อมกันกับลูกค้าหลายรายได้

ให้เราหารือเกี่ยวกับวิธีใช้งานเซิร์ฟเวอร์ซ็อกเก็ตที่มีการประมวลผลหลายตัวด้วย fork ใน C เราจะอธิบายเกี่ยวกับตัวอย่างการเขียนโปรแกรมของโปรแกรมฝั่งเซิร์ฟเวอร์และโปรแกรมฝั่งไคลเอ็นต์ ซึ่งเราสามารถบรรลุถึงเซิร์ฟเวอร์ซ็อกเก็ตที่มีการประมวลผลหลายตัวด้วย fork ใน C

การเรียกของระบบ Fork คืออะไร

เมื่อการเรียกของระบบสร้างโคลนของกระบวนการที่มีอยู่ จะเรียกว่าการเรียกของระบบ “fork()” โดยพื้นฐานแล้วมันจะแยกโปรแกรมที่รันอยู่ออกเป็นสองกระบวนการแยกกันซึ่งเรียกว่าผู้ปกครองและลูก พารามิเตอร์ทั้งหมดจะเหมือนกันสำหรับกระบวนการลูกและพาเรนต์ ยกเว้นว่ามี PID ที่แตกต่างกัน การเรียกของระบบนี้ส่งคืนสิ่งต่อไปนี้:

  1. PID ของกระบวนการย่อยไปยังผู้ปกครอง
  2. ศูนย์ (0) สำหรับเด็ก

ตัวอย่างการเขียนโปรแกรม 1:โปรแกรมฝั่งเซิร์ฟเวอร์

#รวม
#รวม
#รวม
#รวม
#รวม
#รวม
#รวม
#รวม

#กำหนดพอร์ต 8888

int หลัก ()
{
    int serSoc, cliSoc;
    โครงสร้าง sockaddr_in serverAddr, clientAddr;
    socklen_t addrSize =ขนาดของ (clientAddr);
    บัฟเฟอร์ถ่าน [1024];
    int clientCount =0;

    // สร้างซ็อกเก็ตเซิร์ฟเวอร์
    serSoc =ซ็อกเก็ต (AF_INET, SOCK_STREAM, 0);
    ถ้า (serSoc <0) {
        perror ("ข้อผิดพลาดในการสร้างซ็อกเก็ต");
        ออก (1);
   

    printf ("สร้างซ็อกเก็ตเซิร์ฟเวอร์แล้ว\n");

    // ให้เราตั้งค่าที่อยู่เซิร์ฟเวอร์
    serverAddr.sin_family =AF_INET;
    serverAddr.sin_port =htons (พอร์ต);
    serverAddr.sin_addr.s_addr =INADDR_ANY;

   
    ถ้า (ผูก (serSoc, (struct sockaddr *) &serverAddr, sizeof (serverAddr)) <0) {
        perror ("ข้อผิดพลาดในการผูก");
        ออก (1);
   

    // เริ่มฟังการเชื่อมต่อที่เข้ามา
    ถ้า (ฟัง (serSoc, 5) ==0) {
        printf ("กำลังฟังการเชื่อมต่อ...\n");
    } อื่น ๆ {
        perror ("ข้อผิดพลาดในการฟัง");
        ออก (1);
   

    ในขณะที่ (1) {
        // ให้เรายอมรับการเชื่อมต่อลูกค้า
        cliSoc  =ยอมรับ (serSoc, (struct sockaddr* )&clientAddr, &addrSize);
        ถ้า (cliSoc  <0) {
            perror("เกิดข้อผิดพลาดในการรับการเชื่อมต่อ");
            ออก (1);
       

        // เพิ่มจำนวนลูกค้าและแสดงข้อมูลลูกค้า

        ลูกค้านับ ++;
        printf("ยอมรับการเชื่อมต่อจากไคลเอนต์ %d:%s:%d\n", clientCount, inet_ntoa (clientAddr.sin_addr), ntohs (clientAddr.sin_port));
        printf ("ลูกค้าทั้งหมดเชื่อมต่อ:%d\n", clientCount);

       
        pid_t pid =ทางแยก ();

        ถ้า (pid ==0) {
            // กระบวนการลูก

           
            ปิด (serSoc);

            // รับข้อความจากลูกค้า
            ในขณะที่ (1) {
                memset (บัฟเฟอร์, 0, ขนาดของ (บัฟเฟอร์));
                if (recv (cliSoc , บัฟเฟอร์, ขนาดของ (บัฟเฟอร์), 0) <0) {
                    perror ("ข้อผิดพลาดในการรับข้อมูล");
                    ออก (1);
               

                printf ("ได้รับข้อมูลจากไคลเอนต์ %d:%s\n", clientCount, บัฟเฟอร์);

                // สะท้อนข้อความที่ได้รับกลับไปยังไคลเอนต์
                ถ้า (ส่ง (cliSoc , บัฟเฟอร์, strlen (บัฟเฟอร์), 0)  0) {
            // กระบวนการหลัก

           
            ปิด(cliSoc );
        } อื่น ๆ {
            perror ("ข้อผิดพลาดในการฟอร์ก");
            ออก (1);
        }
   

    // ปิดซ็อกเก็ตเซิร์ฟเวอร์
    ปิด (serSoc);

    กลับ 0;

Prการเขียนโปรแกรมตัวอย่าง 2:โปรแกรมฝั่งไคลเอ็นต์

#รวม
#รวม
#รวม
#รวม
#รวม
#รวม
#รวม
#รวม
#กำหนดพอร์ต 8888
#define SERVER_IP "127.0.0.1"

int หลัก ()
{
    int cliSoc;
    โครงสร้าง sockaddr_in serverAddr;
    บัฟเฟอร์ถ่าน [1024];
    // สร้างซ็อกเก็ตไคลเอ็นต์
    cliSoc  =ซ็อกเก็ต (AF_INET, SOCK_STREAM, 0);
    ถ้า (cliSoc  <0) {
        perror ("ข้อผิดพลาดในการสร้างซ็อกเก็ต");
        ออก (1);
   

    printf("ไคลเอนต์ %d ซ็อกเก็ตที่สร้างแล้ว\n", getpid ());

    // ตั้งค่าพารามิเตอร์ที่อยู่เซิร์ฟเวอร์
    serverAddr.sin_family =AF_INET;
    serverAddr.sin_port =htons (พอร์ต);
    serverAddr.sin_addr.s_addr =inet_addr (SERVER_IP);
    // เชื่อมต่อกับเซิร์ฟเวอร์
    ถ้า (เชื่อมต่อ (cliSoc , (struct sockaddr*) &serverAddr, sizeof (serverAddr)) <0) {
        perror("ข้อผิดพลาดในการเชื่อมต่อกับเซิร์ฟเวอร์");
        ออก (1);
   

    printf ("เชื่อมต่อกับเซิร์ฟเวอร์แล้ว\n");
    ในขณะที่ (1) {
        // อ่านอินพุตจากผู้ใช้
        printf ("ไคลเอนต์ %d - ป้อนข้อความ:", getpid ());
        fgets (บัฟเฟอร์, ขนาดของ (บัฟเฟอร์), stdin);

       
        ถ้า (ส่ง (cliSoc บัฟเฟอร์ strlen (บัฟเฟอร์) 0) <0) {
            perror ("ข้อผิดพลาดในการส่งข้อมูล");
            ออก (1);

        }
        // รับการตอบกลับจากเซิร์ฟเวอร์
        memset (บัฟเฟอร์, 0, ขนาดของ (บัฟเฟอร์));
        if (recv (cliSoc , บัฟเฟอร์, ขนาดของ (บัฟเฟอร์), 0) <0) {
            perror ("ข้อผิดพลาดในการรับข้อมูล");
            ออก (1);
        }
        printf ("ไคลเอนต์ %d - การตอบสนองของเซิร์ฟเวอร์:%s\n", getpid (), บัฟเฟอร์);
   

    // ปิดซ็อกเก็ตไคลเอนต์
    ปิด (cliSoc );
    กลับ 0;

เอาต์พุต:

**การรวบรวมโปรแกรมเซิฟเวอร์**
$ gcc ser.c -o เซอร์
$ ./เซอร์
สร้างซ็อกเก็ตเซิร์ฟเวอร์แล้ว
กำลังฟังการเชื่อมต่อ...
สร้างซ็อกเก็ตเซิร์ฟเวอร์แล้ว
กำลังฟังการเชื่อมต่อ...
ยอมรับการเชื่อมต่อจากไคลเอนต์ 1:127.0.0.1:59074
ลูกค้าทั้งหมดที่เชื่อมต่อ:1
รับข้อมูลจากลูกค้า 1:hii admin
ยอมรับการเชื่อมต่อจากไคลเอนต์ 2:127.0.0.1:40192
ลูกค้าทั้งหมดที่เชื่อมต่อ:2
รับข้อมูลจากลูกค้า 2:สวัสดีทุกคน
**การรวบรวมโปรแกรมไคลเอนต์ 1**
$ gcc cel.c -o เซล
$ ./cel
สร้างซ็อกเก็ตไคลเอ็นต์ 4007 แล้ว
เชื่อมต่อกับเซิร์ฟเวอร์แล้ว
ลูกค้า 4007 - ป้อนข้อความ:hii admin

**การรวบรวมโปรแกรมไคลเอนต์ 2**
$ gcc cel.c -o เซล
$ ./cel
สร้างซ็อกเก็ตไคลเอ็นต์ 4024 แล้ว
เชื่อมต่อกับเซิร์ฟเวอร์แล้ว
ลูกค้า 4024 - ป้อนข้อความ:สวัสดีทุกคน

คำอธิบาย:

ในตัวอย่างการเขียนโปรแกรมนี้ เราได้อธิบายการใช้งานเซิร์ฟเวอร์ซ็อกเก็ตที่มีการประมวลผลหลายตัวด้วยทางแยกในภาษา C ที่นี่ในโปรแกรมฝั่งเซิร์ฟเวอร์ เราสร้างซ็อกเก็ตเซิร์ฟเวอร์ ผูกเข้ากับที่อยู่และพอร์ตเฉพาะ และรับฟังการเชื่อมต่อขาเข้า เมื่อไคลเอนต์เชื่อมต่อ กระบวนการลูกจะถูกสร้างขึ้นโดยใช้ “fork()” ช่วยให้สามารถจัดการไคลเอนต์หลายตัวพร้อมกันได้ กระบวนการลูกได้รับข้อความจากไคลเอนต์และแสดงข้อมูลด้วย ID ของลูกค้า เซิร์ฟเวอร์ซ็อกเก็ตที่มีการประมวลผลหลายตัวนี้ช่วยให้เราสามารถสื่อสารกับไคลเอนต์จำนวน "n" ได้พร้อมกัน

บทสรุป

เราได้พูดคุยกันเกี่ยวกับการใช้งานเซิร์ฟเวอร์ซ็อกเก็ตการประมวลผลหลายตัวด้วย fork ใน C การใช้การเรียกระบบ fork ช่วยให้เราสามารถจัดการการเชื่อมต่อไคลเอนต์หลายตัวพร้อมกันได้ ช่วยให้สามารถสื่อสารพร้อมกันกับลูกค้าหลายรายและจัดการคำขอของลูกค้าได้อย่างมีประสิทธิภาพ

เกี่ยวกับผู้เขียน

สร้างเซิร์ฟเวอร์ซ็อกเก็ตหลายกระบวนการใน C โดยใช้ Fork

บัมเด็บ โกช

Bamdeb Ghosh มีประสบการณ์ตรงในโดเมนเครือข่ายไร้สาย เขาเป็นผู้เชี่ยวชาญในการวิเคราะห์การจับ Wireshark บนเครือข่ายไร้สายหรือแบบมีสาย พร้อมด้วยความรู้เกี่ยวกับ Android, Bluetooth, คำสั่ง Linux และ Python ติดตามเว็บไซต์ของเขา:wifisharks.com