ความลับสำคัญของการเชื่อมต่อ TCP ของ Network Packet Broker: ไขความลึกลับของความจำเป็นในการจับมือสามครั้ง

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

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

กระบวนการจับมือสามทางของ TCP และการเปลี่ยนสถานะ
TCP เป็นโปรโตคอลการขนส่งแบบเชื่อมต่อ ซึ่งจำเป็นต้องมีการสร้างการเชื่อมต่อก่อนการส่งข้อมูล กระบวนการสร้างการเชื่อมต่อนี้ดำเนินการโดยการจับมือสามทาง

 การจับมือสามทางของ TCP

มาดูแพ็กเก็ต TCP ที่ถูกส่งในแต่ละการเชื่อมต่อกันอย่างใกล้ชิดยิ่งขึ้น

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

 แพ็กเก็ต SYN

เมื่อไคลเอ็นต์เริ่มต้นการเชื่อมต่อ ไคลเอ็นต์จะสร้างหมายเลขลำดับเริ่มต้นแบบสุ่ม (client_isn) และวางไว้ในฟิลด์ "หมายเลขลำดับ" ของส่วนหัว TCP ขณะเดียวกัน ไคลเอ็นต์จะตั้งค่าตำแหน่งแฟล็ก SYN เป็น 1 เพื่อระบุว่าแพ็กเก็ตขาออกเป็นแพ็กเก็ต SYN ไคลเอ็นต์ระบุว่าต้องการสร้างการเชื่อมต่อกับเซิร์ฟเวอร์โดยการส่งแพ็กเก็ต SYN แรกไปยังเซิร์ฟเวอร์ แพ็กเก็ตนี้ไม่มีข้อมูลชั้นแอปพลิเคชัน (นั่นคือ ข้อมูลที่ส่ง) ณ จุดนี้ สถานะของไคลเอ็นต์จะถูกทำเครื่องหมายเป็น SYN-SENT

แพ็กเก็ต SYN+ACK

เมื่อเซิร์ฟเวอร์ได้รับแพ็กเก็ต SYN จากไคลเอ็นต์ เซิร์ฟเวอร์จะสุ่มกำหนดค่าหมายเลขซีเรียลของตัวเอง (server_isn) แล้วใส่หมายเลขนั้นลงในฟิลด์ "หมายเลขซีเรียล" ของส่วนหัว TCP จากนั้นเซิร์ฟเวอร์จะป้อน client_isn + 1 ลงในฟิลด์ "หมายเลขการรับทราบ" และตั้งค่าบิต SYN และ ACK ให้เป็น 1 สุดท้าย เซิร์ฟเวอร์จะส่งแพ็กเก็ตไปยังไคลเอ็นต์ ซึ่งไม่มีข้อมูลชั้นแอปพลิเคชัน (และไม่มีข้อมูลที่เซิร์ฟเวอร์จะส่ง) ในขณะนี้ เซิร์ฟเวอร์อยู่ในสถานะ SYN-RCVD

แพ็กเก็ต ACK

เมื่อไคลเอ็นต์ได้รับแพ็กเก็ตจากเซิร์ฟเวอร์แล้ว ไคลเอ็นต์จำเป็นต้องดำเนินการปรับแต่งต่อไปนี้เพื่อตอบสนองต่อแพ็กเก็ตตอบกลับสุดท้าย: ขั้นแรก ไคลเอ็นต์ตั้งค่าบิต ACK ของส่วนหัว TCP ของแพ็กเก็ตตอบกลับเป็น 1 ขั้นที่สอง ไคลเอ็นต์ป้อนค่า server_isn + 1 ในช่อง "ยืนยันหมายเลขคำตอบ" ขั้นสุดท้าย ไคลเอ็นต์จะส่งแพ็กเก็ตไปยังเซิร์ฟเวอร์ แพ็กเก็ตนี้สามารถส่งข้อมูลจากไคลเอ็นต์ไปยังเซิร์ฟเวอร์ได้ เมื่อการดำเนินการเหล่านี้เสร็จสมบูรณ์ ไคลเอ็นต์จะเข้าสู่สถานะ ESTABLISHED

เมื่อเซิร์ฟเวอร์ได้รับแพ็คเก็ตการตอบกลับจากไคลเอนต์ เซิร์ฟเวอร์จะเปลี่ยนเป็นสถานะ ESTABLISHED อีกด้วย

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

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

การจับมือสามทางสามารถหลีกเลี่ยงการเริ่มต้นการเชื่อมต่อที่ซ้ำกันตามประวัติศาสตร์ได้อย่างมีประสิทธิภาพ (เหตุผลหลัก)
การจับมือสามทางรับประกันว่าทั้งสองฝ่ายได้รับหมายเลขลำดับเริ่มต้นที่เชื่อถือได้
การจับมือสามทางช่วยหลีกเลี่ยงการสิ้นเปลืองทรัพยากร

เหตุผลที่ 1: หลีกเลี่ยงการรวมข้อมูลซ้ำซ้อนทางประวัติศาสตร์
โดยสรุป เหตุผลหลักของการจับมือแบบสามทางคือเพื่อหลีกเลี่ยงความสับสนที่เกิดจากการเริ่มต้นการเชื่อมต่อซ้ำซ้อนแบบเดิม ในสภาพแวดล้อมเครือข่ายที่ซับซ้อน การส่งแพ็กเก็ตข้อมูลจะไม่ถูกส่งไปยังโฮสต์ปลายทางตามเวลาที่กำหนดเสมอไป และแพ็กเก็ตข้อมูลเก่าอาจมาถึงโฮสต์ปลายทางก่อนเนื่องจากความแออัดของเครือข่ายและเหตุผลอื่นๆ เพื่อหลีกเลี่ยงปัญหานี้ TCP จึงใช้การจับมือแบบสามทางเพื่อสร้างการเชื่อมต่อ

การจับมือสามทางช่วยหลีกเลี่ยงการเชื่อมต่อซ้ำซ้อนในอดีต

เมื่อไคลเอนต์ส่งแพ็กเก็ตการสร้างการเชื่อมต่อ SYN หลายรายการติดต่อกัน ในสถานการณ์เช่นเครือข่ายคับคั่ง อาจเกิดสิ่งต่อไปนี้:

1- แพ็กเก็ต SYN เก่ามาถึงเซิร์ฟเวอร์ก่อนแพ็กเก็ต SYN ล่าสุด
2- เซิร์ฟเวอร์จะตอบกลับแพ็กเก็ต SYN + ACK ไปยังไคลเอนต์หลังจากได้รับแพ็กเก็ต SYN เก่า
3- เมื่อไคลเอนต์ได้รับแพ็กเก็ต SYN + ACK ไคลเอนต์จะพิจารณาว่าการเชื่อมต่อนั้นเป็นการเชื่อมต่อตามประวัติ (หมายเลขลำดับหมดอายุหรือหมดเวลา) ตามบริบทของตัวเอง จากนั้นจึงส่งแพ็กเก็ต RST ไปยังเซิร์ฟเวอร์เพื่อยกเลิกการเชื่อมต่อ

การเชื่อมต่อแบบสองแฮนด์เชค (two-handshake) จะไม่สามารถระบุได้ว่าการเชื่อมต่อปัจจุบันเป็นการเชื่อมต่อในอดีตหรือไม่ แฮนด์เชคแบบสามทางช่วยให้ไคลเอ็นต์สามารถระบุได้ว่าการเชื่อมต่อปัจจุบันเป็นการเชื่อมต่อในอดีตหรือไม่ โดยพิจารณาจากบริบทเมื่อพร้อมที่จะส่งแพ็กเก็ตที่สาม:

1- หากเป็นการเชื่อมต่อตามประวัติ (หมายเลขลำดับหมดอายุหรือหมดเวลา) แพ็กเก็ตที่ส่งโดยการจับมือครั้งที่สามจะเป็นแพ็กเก็ต RST เพื่อยกเลิกการเชื่อมต่อตามประวัติ
2- หากไม่ใช่การเชื่อมต่อตามประวัติศาสตร์ แพ็กเก็ตที่ส่งเป็นครั้งที่สามจะเป็นแพ็กเก็ต ACK และทั้งสองฝ่ายที่สื่อสารกันก็จะสร้างการเชื่อมต่อสำเร็จ

ดังนั้น เหตุผลหลักที่ TCP ใช้การจับมือสามทางก็คือ เพื่อเริ่มต้นการเชื่อมต่อเพื่อป้องกันการเชื่อมต่อในอดีต

เหตุผลที่ 2: เพื่อซิงโครไนซ์หมายเลขลำดับเริ่มต้นของทั้งสองฝ่าย
โปรโตคอล TCP ทั้งสองด้านต้องรักษาหมายเลขลำดับ ซึ่งเป็นปัจจัยสำคัญที่ทำให้มั่นใจได้ว่าการส่งข้อมูลมีความน่าเชื่อถือ หมายเลขลำดับมีบทบาทสำคัญในการเชื่อมต่อ TCP โดยทำหน้าที่ดังต่อไปนี้:

ผู้รับสามารถกำจัดข้อมูลที่ซ้ำซ้อนและรับรองความถูกต้องของข้อมูลได้

ผู้รับสามารถรับแพ็คเก็ตตามลำดับหมายเลขเพื่อให้แน่ใจว่าข้อมูลมีความสมบูรณ์

● หมายเลขลำดับสามารถระบุแพ็กเก็ตข้อมูลที่อีกฝ่ายได้รับ ทำให้สามารถส่งข้อมูลได้อย่างน่าเชื่อถือ

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

ซิงโครไนซ์หมายเลขซีเรียลเริ่มต้นของทั้งสองฝ่าย

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

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

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

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

หลีกเลี่ยงการสิ้นเปลืองทรัพยากร

ดังนั้นเพื่อให้แน่ใจถึงความเสถียรและความน่าเชื่อถือของการเชื่อมต่อเครือข่าย TCP จึงใช้การจับมือสามทางเพื่อสร้างการเชื่อมต่อเพื่อหลีกเลี่ยงการเกิดปัญหาเหล่านี้

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

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


เวลาโพสต์: 8 ม.ค. 2568