12.5. ความน่าเชื่อถือ -- ลำดับ, ACK และการส่งซ้ำ¶
ชั้นการจัดกรอบตรวจจับความเสียหายด้วย CRC ชั้นความน่าเชื่อถือเปลี่ยน "การตรวจพบความเสียหาย" ให้กลายเป็น "แอปพลิเคชันไม่เห็นข้อมูลที่เสียหายเลย" โดยการต่อรองส่งข้อมูลซ้ำเมื่อใดก็ตามที่แพ็กเก็ตไม่มาถึงในสภาพสมบูรณ์
12.5.1. หมายเลขลำดับ¶
แต่ละส่วนหัวแพ็กเก็ตมีหมายเลขลำดับขนาดหนึ่งไบต์ แยกกันสำหรับแต่ละทิศทางการรับส่ง ผู้ส่งเพิ่มค่าตัวนับก่อนส่ง ผู้รับตรวจสอบว่าลำดับของแต่ละแพ็กเก็ตที่ได้รับคือลำดับก่อนหน้าบวกหนึ่ง (ตามแบบโมดูโล 256)
ผู้รับอาจพบสามสถานการณ์แทนที่จะเป็นแพ็กเก็ตที่มาในลำดับถูกต้อง:
หมายเลขลำดับที่คาดไว้ พร้อม CRC ที่ถูกต้อง แพ็กเก็ตถูกส่งต่อไปยังชั้นถัดไป
หมายเลขลำดับที่คาดไว้ พร้อม CRC ที่ผิดพลาด ผู้รับทิ้งแพ็กเก็ตและ (หากมีการต่อรอง ACK) ส่ง NAK ขอให้ส่งซ้ำ
หมายเลขลำดับที่สูงกว่าที่คาดไว้หนึ่งหมายเลข พร้อม CRC ที่ถูกต้อง ผู้รับรู้ว่าแพ็กเก็ตก่อนหน้าหายไป จึงส่ง NAK อ้างอิงลำดับที่ขาดหายและเก็บอันใหม่ไว้ก่อน
กรณีซ้ำซ้อน (การส่งซ้ำที่มาถึงหลังจากต้นฉบับผ่านมาได้แล้ว) ได้รับการจัดการโดยการตรวจสอบเทียบกับตัวนับที่คาดไว้: หากลำดับนั้น ล้าหลัง ลำดับที่คาดไว้ แพ็กเก็ตนั้นคือสำเนาซ้ำซ้อนและผู้รับจะทิ้งมันทิ้งหลังจากส่ง ACK ที่ผู้ส่งเห็นชัดว่าไม่ได้รับในครั้งแรก
12.5.2. ACK และ NAK¶
บิตแฟล็กสองบิตในส่วนหัวแพ็กเก็ตรองรับการรับส่งข้อมูลด้านความน่าเชื่อถือ:
ACK_REQที่ตั้งไว้บนแพ็กเก็ตขาออกหมายความว่า "ฉันต้องการการตอบรับกลับมา" แพ็กเก็ตข้อมูลปกติจะตั้งค่านี้ ส่วนการ ping สถานะและเหตุการณ์ครั้งเดียวอาจไม่ตั้งACKที่ตั้งไว้บนแพ็กเก็ตหมายความว่า "แพ็กเก็ตนี้คือการตอบรับสำหรับหมายเลขลำดับในส่วนหัว" โดยไม่มีเพย์โหลดของตัวเองNAKที่ตั้งไว้หมายความว่า "แพ็กเก็ตนี้ปฏิเสธแพ็กเก็ตก่อนหน้า" -- มักเกิดจาก CRC ที่ผิดพลาดหรือช่องว่างในหมายเลขลำดับ ส่วนหัวชี้ให้ผู้ส่งรู้ว่าต้องส่งลำดับใดซ้ำ
ผู้ส่งทำงานแบบวนซ้ำแบบหยุดและรอ: ส่งแพ็กเก็ตหนึ่งชิ้นที่ต้องการการตอบรับ แล้วรอ ACK (หรือ NAK) ที่ตรงกันก่อนส่งอันถัดไป โมเดลการส่งครั้งละหนึ่งชิ้นทำให้สถานะของผู้ส่งมีขอบเขตจำกัด -- สักไม่กี่ร้อยไบต์บนกล้องที่เล็กที่สุด -- และเหมาะกับบทบาทของโปรโตคอลในฐานะช่องควบคุมระหว่างสองจุดสิ้นสุดมากกว่าท่อที่ปรับแต่งเพื่อปริมาณงานที่ผ่านได้ เมื่อได้รับ NAK ผู้ส่งจะส่งแพ็กเก็ตเดิมซ้ำพร้อมตั้งค่าแฟล็ก RTX เพื่อให้ผู้รับรู้ว่าเป็นการลองใหม่
12.5.3. ระยะเวลาการส่งซ้ำ¶
หากไม่มี ACK หรือ NAK มาถึงภายใน ระยะเวลาหมดเวลาการส่งซ้ำ ผู้ส่งจะส่งแพ็กเก็ตที่กำลังบินอยู่ซ้ำโดยอัตโนมัติ ค่าเริ่มต้นของระยะหมดเวลาคือ 500 ms และจะเพิ่มเป็นสองเท่าในแต่ละการลองซ้ำ (1 วินาที, 2 วินาที, ...) หลังจากจำนวนการลองซ้ำที่กำหนดไว้ -- ค่าเริ่มต้นสามครั้ง -- ผู้ส่งจะยอมแพ้และรายงานข้อผิดพลาดการขนส่งไปยังแอปพลิเคชัน
การเพิ่มระยะหมดเวลาเป็นสองเท่าคือรูปแบบ exponential backoff มาตรฐาน ระยะหมดเวลาครั้งแรกที่สั้นช่วยตรวจจับแพ็กเก็ตที่หายไปได้อย่างรวดเร็ว การเพิ่มสองเท่าหมายความว่าโฮสต์ที่ยุ่งอยู่สักสองสามร้อยมิลลิวินาทีจะไม่กระตุ้นให้เกิดการส่งซ้ำจำนวนมากที่ยิ่งเพิ่มภาระ
12.5.4. การกำหนดค่าความน่าเชื่อถือ¶
ทั้งสองฝั่งสามารถปิดส่วนต่าง ๆ ของชั้นความน่าเชื่อถือได้โดยข้อตกลง เมื่อแอปพลิเคชันสามารถรับการสูญเสียข้อมูลได้:
protocol.init(ack=False)ปิดใช้งาน ACK ต่อแพ็กเก็ต ผู้ส่งส่งและลืม ผู้รับส่งมอบสิ่งที่มาถึง เหมาะสำหรับการสตรีมข้อมูลเซนเซอร์ที่ตัวอย่างเก่าเป็นที่ยอมรับได้protocol.init(seq=False)ปิดการติดตามหมายเลขลำดับ ซึ่งหมายความว่าปิด ACK ด้วย มีประโยชน์เฉพาะบนการขนส่งที่เชื่อถือได้อย่างสมบูรณ์protocol.init(crc=False)ปิดการตรวจสอบ CRC แต่เหลือส่วนที่เหลือของการจัดกรอบไว้ คุ้มค่าที่จะทำเฉพาะเมื่อการขนส่งนั้นแข็งแกร่งพอที่ข้อผิดพลาด CRC ไม่เกิดขึ้น
ค่าเริ่มต้น -- ทุกอย่างเปิดใช้งาน -- คือจุดเริ่มต้นที่ถูกต้องสำหรับทุกเซสชันการดีบักระหว่างโฮสต์กับกล้อง เมื่อแอปพลิเคชันอยู่ในโหมดใช้งานจริง การแลกเปลี่ยนจะขึ้นอยู่กับข้อมูลและการขนส่งของแอปพลิเคชันนั้น ๆ โดยเฉพาะ
12.5.5. รหัสสถานะ¶
เมื่อข้อผิดพลาดการขนส่งส่งต่อถึงโค้ดแอปพลิเคชัน มันมาในรูปแบบรหัสสถานะ ไลบรารีโปรโตคอลกำหนดไว้สิบรหัส:
SUCCESS-- การดำเนินการเสร็จสมบูรณ์FAILED-- คำสั่งล้มเหลวด้วยเหตุผลที่ไม่ระบุINVALID-- ผู้รับปฏิเสธคำสั่งหรือหนึ่งในอาร์กิวเมนต์TIMEOUT-- ตัวจับเวลาการลองซ้ำหมดเวลาBUSY-- กล้องกำลังยุ่ง (มักเป็นช่องที่ถูกล็อก)CHECKSUM-- CRC ของส่วนหัวหรือเพย์โหลดไม่ตรงกันSEQUENCE-- หมายเลขลำดับไม่เป็นไปตามลำดับเกินกว่าที่ชั้นนั้นจะกู้คืนได้OVERFLOW-- เพย์โหลดเกินขนาดสูงสุดที่ต่อรองไว้FRAGMENT-- ข้อความหลายส่วนมาถึงโดยขาดชิ้นส่วนUNKNOWN-- การตรวจจับแบบครอบคลุมสำหรับสภาวะที่ไม่คาดคิดอย่างแท้จริง
โค้ดฝั่งโฮสต์ที่เรียก channel_read() จะเห็นสิ่งเหล่านี้ในรูปแบบ exception ของ Python โค้ดแอปพลิเคชันฝั่งกล้องที่เลือกใช้การจัดการข้อผิดพลาดแบบกำหนดเองจะเห็นเป็นค่าที่คืนมาจากคอลแบ็กแบ็กเอนด์ แอปกล้องส่วนใหญ่ไม่จำเป็นต้องดูรหัสสถานะเลย -- ไลบรารีจัดการการลองซ้ำ และเฉพาะความล้มเหลวที่กู้คืนไม่ได้จริง ๆ (เช่น การขนส่งหายไปเอง) เท่านั้นที่จะถึงแอปพลิเคชัน
เมื่อการจัดกรอบพร้อมสำหรับการตรวจจับความเสียหายและความน่าเชื่อถือพร้อมสำหรับการกู้คืน งานระดับสายก็เสร็จสิ้น โค้ดแอปพลิเคชันเห็นแพ็กเก็ตที่จัดกรอบแล้ว เรียงลำดับแล้ว สมบูรณ์แล้ว ไบต์ภายในนั้นอิสระที่จะมีความหมายอะไรก็ได้ตามที่ช่องด้านบนต้องการ