หากแพ็กเก็ต TCP ได้รับการตอบรับบางส่วนกลไกการส่งสัญญาณใหม่จะตอบสนองอย่างไร


12

หากไคลเอ็นต์ tcp ส่งแพ็กเก็ตโดยมีหมายเลขลำดับจาก 10,000 ถึง 20000 ไปยังเซิร์ฟเวอร์ tcp tcp จะตอบกลับด้วย ACK พร้อมด้วย seq_ack 20001

ถ้าฉันดักจับแพ็กเก็ต TCP จากไคลเอนต์และแบ่งแพ็คเก็ตเป็น 2 เซ็กเมนต์ TCP หนึ่งอันที่มี seq จาก 10,000 ถึง 15,000 และอีกอันหนึ่งที่มี seq จาก 15001 ถึง 20000 จากนั้นเซ็กเมนต์ TCP 2 อันเหล่านี้จะถูกส่งไปยังเซิร์ฟเวอร์ TCP สมมติว่าส่วนที่สองหายไปในเส้นทาง เซิร์ฟเวอร์ TCP จะตอบสนอง ACK ด้วย seq_ack 15001

ตอนนี้เนื่องจากไคลเอนต์ TCP ส่งแพ็กเก็ตอินทิกรัลด้วย seq 10,000 ถึง 20000 แต่ได้รับ ACK ที่มี 15001 จากมุมมองของลูกค้านี่เป็นเรื่องแปลก มันจะตอบสนองอย่างไร ในทางทฤษฎีไคลเอนต์ควรส่งใหม่ไบต์จาก seq 15001 ถึง 20000 กล่าวคือไคลเอนต์จะส่งแพ็กเก็ตใหม่จาก seq 15001 แต่วิธีการเกี่ยวกับการปฏิบัติในการใช้งานสแต็ก TCP มันเป็นเช่นเดียวกับในทฤษฎี?

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

คำตอบ:


8

นี้เรียกว่าการรับรู้การคัดเลือกและรวมอยู่ในข้อกำหนด TCP ที่กำหนดไว้ในRFC 2018 สิ่งนี้จะช่วยให้ไคลเอนต์ส่งใหม่เพียงไบต์ 15001 ถึง 20000 (เนื่องจากพวกเขาอยู่ในแพ็กเก็ต / เซ็กเมนต์ต่าง ๆถ้าคุณแยกพวกเขาตามที่คุณพูด) แต่น่าสนใจยิ่งขึ้น

จาก RFC 2018:

เมื่อรับ ACK ที่มีตัวเลือก SACK ผู้ส่งข้อมูลควรบันทึกการตอบรับแบบเลือกเพื่อการอ้างอิงในอนาคต ผู้ส่งข้อมูลจะถือว่ามีคิวการส่งสัญญาณใหม่ที่มีส่วนที่ถูกส่ง แต่ยังไม่ได้รับการยอมรับตามลำดับหมายเลข

สนับสนุนSACKจะไม่ได้กำหนดไว้ในข้อกำหนด TCP หากไคลเอนต์หรือเซิร์ฟเวอร์ไม่สนับสนุนการตอบรับเลือกแน่นอนไบต์ทั้งหมด 10,000 ถึง 20000 จะต้องมีการส่งอีกครั้ง

ในการใช้งานสแต็ก TCP มันเหมือนกับในทฤษฎีหรือไม่

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

อย่างไรก็ตามสมมติฐานเหล่านี้ควรเป็นจริงแม้ว่าคุณจะจัดการแพ็กเก็ตด้วยตนเองตามที่คุณระบุ เป็นต่อRFC 793อย่างน้อยหน้าต่างข้อมูลทั้งหมดจะต้องส่งใหม่ แต่ reciever ไม่ทราบว่าข้อมูลที่ได้รับเป็นอย่างน้อยที่ถูกต้อง สำหรับรายละเอียดการใช้งานส่วน 3.3 - หมายเลขลำดับจาก RFC 793

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


มันค่อนข้างแปลกสำหรับฉันเพราะ TCP เป็นโปรโตคอลแบบไบต์ต่อสตรีม เหตุใดจึงควรส่งสัญญาณซ้ำทั้งเซกเมนต์ สำหรับฉันแล้ว TCP ที่ไม่มี SAKC นั้นเป็นโปรโตคอลสตรีมที่เน้นเซ็กเมนต์ แต่ TCP ที่มี Sack นั้นเป็นไบต์ที่มุ่งเน้นจริง ฉันคิดว่า RFC ไม่ได้อธิบายรายละเอียดเกี่ยวกับเรื่องนี้โดยเฉพาะ
misteryes

วิธีที่สแต็ก TCP จัดการบัฟเฟอร์การส่งมันเหมือนกับที่ฉันเขียนไว้ในคำถามที่อัปเดต
misteryes

@misteryes บทความนี้สรุปกระบวนการ (ด้วยไดอะแกรมที่ยอดเยี่ยมเช่นกัน!)
Breakthrough

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

1
ฉันรู้จัก SACK ก่อนโพสต์คำถามนี้ ในตอนแรกฉันไม่คิดว่า SACK จะเกี่ยวข้องกับคำถามนี้ ในความคิดของฉันถ้า TCP ไม่ได้เป็นแบบไบต์ แต่เป็นเซ็กเมนต์ดังนั้น SACK ก็ควรจะเหมือนกัน ความแตกต่างระหว่างการเปิดใช้งาน SACK และปิดใช้งาน SACK คือด้วย SACK, TCP ช่วยให้รูลำดับใน ack_seq แต่ฉันคิดว่ารูลำดับนั้นสอดคล้องกับส่วน ในขณะที่คุณพูดหลุมสามารถครึ่ง / ส่วนหนึ่งของส่วน
misteryes

3

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

  1. เมื่อใดก็ตามที่ ACK มาถึงให้เลื่อนตัวชี้ไปยังไบต์แรกที่ไม่ได้รับการยอมรับตามลำดับและละทิ้งบัฟเฟอร์ที่ไม่จำเป็นตอนนี้
  2. เมื่อความต้องการเกิดขึ้นสำหรับการส่งใหม่ (การส่งใหม่อย่างรวดเร็วหรือหมดเวลาไม่ทันทีหลังจากได้รับ ACK แรก!) มันจะส่งอีกครั้งในขนาดเซกเมนต์ที่ถูกต้องในปัจจุบันเริ่มต้นจากตัวชี้ไปยังไบต์ที่ไม่ได้รับการยอมรับ

การดำเนินการทั้งสองจะทำอย่างเป็นอิสระจากขนาดเซ็กเมนต์ไบต์เหล่านี้ถูกส่งมา แต่แรกดังนั้นทฤษฎีควรตรงกับการใช้งานส่วนใหญ่

ให้ฉันให้พื้นหลังอธิบาย:

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

  • มีการแนะนำตัวเลือกต่างๆเช่นการแบก SACK บนการส่งสัญญาณซ้ำ (การใช้งานจริงจะพบสิ่งนี้น้อยมากถ้าหากทั้งหมด)
  • การเปลี่ยนแปลงเส้นทาง MTU เช่นหนึ่งลิงก์ตามการเปลี่ยนแปลงเส้นทางไปเป็น MTU ที่ต่ำกว่าหรือเพิ่มการเชื่อมโยง MTU คอขวด สิ่งนี้จะเกิดขึ้นเมื่อมีการสร้างอุโมงค์ (VPN, PPPoE) หรือโปรโตคอลการกำหนดเส้นทางจะเลือกลิงค์ -MTU ที่แตกต่างกัน สิ่งนี้เกิดขึ้นใน IPv4 พร้อมชุด Don't Fragment (จริงสำหรับ TCPs ที่ทันสมัยที่สุด); เสมอใน TCPv6)

BTW: SACK ไม่ใช่คำตอบที่นี่เนื่องจากผู้รับจะ (โดยทั่วไป) ใช้ SACK เท่านั้นหากรู้จักรูในสตรีมไบต์ (เช่นถ้าแพ็กเก็ตหายไป แต่แพ็กเก็ตต่อไปนี้มาถึง)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.