การเขียนโปรแกรมซ็อกเก็ตใน C ++

Kar Kheiyn Por Kae Rms Xk Ket Ni C



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

การสร้างโมเดลไคลเอ็นต์-เซิร์ฟเวอร์

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

1. ฝั่งเซิร์ฟเวอร์







รหัสสำหรับฝั่งเซิร์ฟเวอร์ของโมเดลมีดังต่อไปนี้ ให้เราดูว่าเกิดอะไรขึ้นในโค้ด:



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

โดยใช้ เนมสเปซ มาตรฐาน -

#กำหนดพอร์ต 8080
#กำหนด MAX_BUF_SIZE 1024

ภายใน หลัก - - -
ภายใน ser_socket, cli_socket -
โครงสร้าง sockaddr_in ser_address, cli_address -
ถ่าน บัฟ - MAX_BUF_SIZE - - - 0 - -

ถ้า - - ser_socket - เบ้า - AF_INET, SOCK_STREAM, 0 - - - - 1 - -
ผิดพลาด - 'ข้อผิดพลาดในการสร้างซ็อกเก็ต' - -
ออก - EXIT_FAILURE - -
-

ser_address. บาป_ครอบครัว - OF_INET -
ser_address. sin_addr - s_addr - INADDR_ANY -
ser_address. บาป_พอร์ต - ตันส์ - ท่าเรือ - -

ถ้า - ผูก - be_socket, - โครงสร้าง ถุงเท้า - - - ser_ที่อยู่, ขนาดของ - ser_address - - - - 1 - -
ผิดพลาด - “ความล้มเหลวในการผูกมัด” - -
ออก - EXIT_FAILURE - -
-

ถ้า - ฟัง - be_socket, 3 - - - 1 - -
ผิดพลาด - “ฟังไม่ออก” - -
ออก - EXIT_FAILURE - -
-

ศาล - 'เซิร์ฟเวอร์กำลังฟังพอร์ต' - ท่าเรือ - - \n - -

socklen_t cli_address_len - ขนาดของ - cli_address - -
ถ้า - - cli_socket - ยอมรับ - be_socket, - โครงสร้าง ถุงเท้า - - - cli_ที่อยู่, - cli_address_len - - - - 1 - -
ผิดพลาด - “ไม่ยอมรับ” - -
ออก - EXIT_FAILURE - -
-

อ่าน - cli_socket, buf, MAX_BUF_SIZE - -
ศาล - 'ข้อความของลูกค้าคือ:' - บัฟ - สิ้นสุด -

ส่ง - cli_socket, 'ข้อความจากเซิร์ฟเวอร์' - สเตรน - 'ข้อความจากเซิร์ฟเวอร์' - - 0 - -

ปิด - cli_socket - -
ปิด - ser_socket - -

กลับ 0 -
-

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



โปรแกรมเริ่มต้นด้วยการรวมไลบรารี: “iostream” สำหรับคำจำกัดความอินพุต/เอาท์พุตมาตรฐาน “cstring” สำหรับฟังก์ชันการจัดการสตริง “unistd.h” เพื่อให้การเข้าถึง API ระบบปฏิบัติการ POSIX และ “arpa/inet.h” เพื่อ ดำเนินการใช้งานอินเทอร์เน็ต คำสั่ง “#define PORT 8080” หมายความว่า กำหนดหมายเลขพอร์ต 8080 ที่เซิร์ฟเวอร์จะรับฟัง “#define MAX_BUF_SIZE 1024” หมายถึงขนาดบัฟเฟอร์สูงสุดสำหรับข้อมูลขาเข้าซึ่งก็คือ 1024





ในฟังก์ชันหลัก ตัวแปรสองตัวจะถูกเตรียมใช้งาน ได้แก่ “ser_socket” และ “cli_socket” เพื่อเป็นตัวแทนของทั้งเซิร์ฟเวอร์และไคลเอนต์ตามลำดับ ตัวแปรอีกสามตัว ได้แก่ “sockaddr_in”, “ser_address” และ “cli_address” ประเภท “struct” จะถูกเตรียมใช้งานเป็นโครงสร้างที่อยู่สำหรับเซิร์ฟเวอร์และไคลเอนต์ หลังจากนั้นบัฟเฟอร์ชื่อ 'buf' จะถูกเตรียมใช้งานซึ่งจะเก็บข้อมูลที่มาจากไคลเอนต์

ฟังก์ชัน socket() ในเงื่อนไข “if” จะสร้างซ็อกเก็ต TCP ใหม่ AF_INET หมายถึง IPv4, SOCK_STREAM แสดงถึงซ็อกเก็ต TCP ที่มุ่งเน้นการเชื่อมต่อและเชื่อถือได้ อาร์กิวเมนต์สุดท้ายซึ่งเป็น 0 ถูกกำหนดไว้เพื่อเลือกโปรโตคอล TCP เริ่มต้น INADDR_ANY ยอมรับการเชื่อมต่อบนที่อยู่ IP ใด ๆ และ htons (PORT) แปลงหมายเลขพอร์ตจาก ลำดับไบต์ของโฮสต์ไปยังลำดับไบต์ของเครือข่าย



เนื่องจากทุกอย่างถูกกำหนดอย่างถูกต้อง ขั้นตอนต่อไปคือการตั้งค่าเซิร์ฟเวอร์เป็นรายการบนพอร์ตที่กำหนด และยอมรับการเชื่อมต่อบนอินเทอร์เฟซเครือข่ายใดๆ ซ็อกเก็ตได้รับข้อมูลใน 'ser_address' โดยวิธีผูก () เราพิมพ์ข้อผิดพลาดและยุติกระบวนการหากการผูกล้มเหลว ฟังก์ชัน Accept() จะเปิดซ็อกเก็ตใหม่สำหรับการเชื่อมต่อกับไคลเอนต์ ในขณะที่ฟังก์ชัน Listen() สั่งให้เซิร์ฟเวอร์รอการเชื่อมต่อขาเข้า หากฟังก์ชัน Accept() ล้มเหลว ข้อความแสดงข้อผิดพลาดจะถูกพิมพ์และฟังก์ชันจะออก

จากนั้น เซิร์ฟเวอร์จะอ่านข้อความไคลเอ็นต์ด้วยฟังก์ชัน read() ลงในบัฟเฟอร์ 'buf' แล้วพิมพ์ลงในคอนโซล เซิร์ฟเวอร์ใช้ฟังก์ชัน send() เพื่อส่งข้อความเพื่อตอบสนองต่อไคลเอ็นต์ สุดท้ายนี้ เมื่อใช้ close() เซิร์ฟเวอร์จะปิดซ็อกเก็ตของไคลเอ็นต์ ยุติโปรแกรมเพื่อให้การเชื่อมต่อทั้งหมดปิดอย่างถูกต้อง และไม่มีความเป็นไปได้ที่ข้อมูลจะรั่วไหล

2. ฝั่งไคลเอ็นต์

ตอนนี้เรามาดูกันว่าเกิดอะไรขึ้นในโมเดลไคลเอนต์:

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

#กำหนดพอร์ต 8080
#define SERVER_IP '127.0.0.1'

ภายใน หลัก - - -
ภายใน cli_socket -
โครงสร้าง sockaddr_in ser_address -
ค่าคงที่ ถ่าน - ข้อความ - 'ลูกค้าส่งคำทักทาย!' -

ถ้า - - cli_socket - เบ้า - AF_INET, SOCK_STREAM, 0 - - - - 1 - -
ผิดพลาด - 'ข้อผิดพลาดในการสร้างซ็อกเก็ต' - -
ออก - EXIT_FAILURE - -
-

ser_address. บาป_ครอบครัว - OF_INET -
ser_address. บาป_พอร์ต - ตันส์ - ท่าเรือ - -

ถ้า - inet_pton - AF_INET, SERVER_IP, - ser_address. sin_addr - - 0 - -
ผิดพลาด - 'ที่อยู่ผิด' - -
ออก - EXIT_FAILURE - -
-

ถ้า - เชื่อมต่อ - cli_socket, - โครงสร้าง ถุงเท้า - - - ser_ที่อยู่, ขนาดของ - ser_address - - - - 1 - -
ผิดพลาด - 'การเชื่อมต่อล้มเหลว' - -
ออก - EXIT_FAILURE - -
-
ส่ง - cli_socket, ข้อความ, สเตรน - ข้อความ - - 0 - -

ถ่าน บัฟ - 1,024 - - - 0 - -
อ่าน - cli_socket, ขนาดของ - บัฟ - - -
มาตรฐาน - ศาล - 'การตอบสนองของเซิร์ฟเวอร์:' - บัฟ - มาตรฐาน - สิ้นสุด -

ปิด - cli_socket - -
กลับ 0 -
-

ให้เราดูโค้ดแต่ละบรรทัดเพื่อทำความเข้าใจวิธีการทำงานของโปรแกรม

ไลบรารีสี่ไลบรารีเดียวกัน – iostream, cstring, unistd.h และ arpa/inet.h – ก็รวมอยู่ในฝั่งไคลเอ็นต์ด้วย หมายเลขพอร์ตยังถูกกำหนดพร้อมกับที่อยู่ IP ของโลคัลโฮสต์ 127.0.0.1 ได้รับข้อความที่จะต้องส่งไปยังเซิร์ฟเวอร์ ไคลเอนต์และเซิร์ฟเวอร์จำเป็นต้องสร้างการเชื่อมต่อตามขั้นตอนต่อไปนี้:

“ถ้า ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1);” สร้างซ็อกเก็ตสำหรับ IPv4 ด้วยประเภทสตรีมและโปรโตคอล TCP เริ่มต้น perror() จะพิมพ์รายละเอียดข้อผิดพลาดหากฟังก์ชัน socket() ไม่สามารถสร้างการเชื่อมต่อและออกจากโปรแกรมได้

“server_address.sin_port = htons(PORT);” ตั้งค่าหมายเลขพอร์ตหลังจากแปลงเป็นลำดับไบต์ของเครือข่าย หลังจากนั้นจะมีข้อความแจ้งข้อผิดพลาดอีกฉบับซึ่งก็คือ 'ที่อยู่ผิด' ซึ่งจะถูกพิมพ์ออกมาหากมีสิ่งผิดปกติเกิดขึ้นกับที่อยู่ โดยการค้นหาที่อยู่ใน “ser_address” ลูกค้าจะเชื่อมต่อกับเซิร์ฟเวอร์ หากการเชื่อมต่อล้มเหลว รายละเอียดข้อผิดพลาดจะถูกพิมพ์ออกมา ฟังก์ชัน send() จะถ่ายโอนข้อความไปยังเซิร์ฟเวอร์ เพื่อให้แน่ใจว่าไม่มีแฟล็กใดๆ

ในการรับและจัดเก็บการตอบกลับจากเซิร์ฟเวอร์ บัฟเฟอร์ชื่อ 'buf' ประเภท 'char' จะถูกเตรียมใช้งาน ฟังก์ชัน read() อ่านการตอบสนองของเซิร์ฟเวอร์ลงในบัฟเฟอร์ สุดท้าย การตอบสนองของเซิร์ฟเวอร์จะถูกพิมพ์ไปยังคอนโซล ในที่สุด การเชื่อมต่อจะถูกปิดโดยใช้คำสั่ง close() เพื่อยุติซ็อกเก็ต ต่อไปนี้เป็นผลลัพธ์ของโปรแกรม:

บทสรุป

การเขียนโปรแกรมซ็อกเก็ตเป็นส่วนสำคัญของการสื่อสารเครือข่ายในสาขาวิทยาการคอมพิวเตอร์ ช่วยให้สามารถพัฒนาแอปพลิเคชันที่สามารถสื่อสารผ่านเครือข่าย ทำให้เกิดความเป็นไปได้ที่หลากหลายตั้งแต่สถาปัตยกรรมไคลเอ็นต์-เซิร์ฟเวอร์แบบธรรมดาไปจนถึงระบบแบบกระจายที่มีโครงสร้าง เมื่อซ็อกเก็ตถูกสร้างขึ้นในบริบทการเขียนโปรแกรม โปรแกรมจะต้องกำหนดค่าคุณลักษณะจุดสิ้นสุด เช่น โปรโตคอล TCP หรือ UDP และที่อยู่เครือข่าย เช่น ที่อยู่ IP และหมายเลขพอร์ต ซ็อกเก็ตเหล่านี้ช่วยให้เซิร์ฟเวอร์ส่งและรับข้อมูลได้ บทความนี้สาธิตตัวอย่างเชิงปฏิบัติเกี่ยวกับวิธีการทำงานของโมเดลไคลเอ็นต์-เซิร์ฟเวอร์ในการเขียนโปรแกรมซ็อกเก็ต