รับทราบความน่าเชื่อถือโดยใช้ UDP


16

ฉันมีคำถามเกี่ยวกับ UDP สำหรับบริบทฉันทำงานในเกมแอ็คชั่นตามเวลาจริง

ฉันได้อ่านบ้างเล็กน้อยเกี่ยวกับความแตกต่างระหว่าง UDP และ TCP และฉันรู้สึกว่าเข้าใจค่อนข้างดี แต่มีชิ้นส่วนหนึ่งที่ไม่เคยรู้สึกถูกต้องและน่าเชื่อถือและมีการตอบรับเป็นพิเศษ ฉันเข้าใจว่า UDP ไม่ได้ให้ความน่าเชื่อถือตามค่าเริ่มต้น (เช่นแพ็คเก็ตสามารถถูกทิ้ง เมื่อจำเป็นต้องมีความน่าเชื่อถือโซลูชันที่ฉันเห็น (ซึ่งเหมาะสมตามแนวคิด) คือการใช้ acceptgments (เช่นเซิร์ฟเวอร์ส่งแพ็กเก็ตไปยังไคลเอ็นต์และเมื่อไคลเอ็นต์ได้รับข้อความนั้นจะส่งการตอบกลับไปยังเซิร์ฟเวอร์) .

จะเกิดอะไรขึ้นเมื่อการตอบรับลดลง

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

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

ฉันรู้สึกว่าตรรกะพื้นฐานของฉันถูกต้องตรงนี้ซึ่งทำให้ฉันมีสองตัวเลือก

  1. ส่งแพ็คเก็ตการตอบรับเพียงครั้งเดียวและหวังว่าจะดีที่สุด
  2. ส่งแพ็คเก็ตการรับทราบจำนวนหนึ่ง (อาจ 3-4) และหวังว่าจะดีที่สุดโดยสมมติว่าจะไม่ทิ้งทั้งหมด

มีคำตอบสำหรับปัญหานี้หรือไม่? ฉันเข้าใจอะไรผิดหรือเปล่า? มีการรับประกันการใช้ UDP บางอย่างที่ฉันไม่ทราบหรือไม่? ฉันลังเลที่จะก้าวไปข้างหน้าด้วยรหัสเครือข่ายมากเกินไปจนกว่าฉันจะรู้สึกสะดวกสบายที่ตรรกะของฉันเป็นเสียง


11
บางทีคุณอาจคิดถึง "หมดเวลา" และ "ลองใหม่"
Kromster กล่าวว่าสนับสนุน Monica

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

10
ไม่มีการรับประกันใด ๆ เลย ขวา. อย่ารวม "ความหวัง" ไว้ในอัลกอริทึมของคุณ พวกเขาจะต้องจัดการกับการรวมกันโชคร้ายใด ๆ ป.ล. เราเปลี่ยนไปใช้ TCP ใน RTS ของเราโดยดูแลการใช้ eberything เนื่องจากเราต้องการการสื่อสารที่เชื่อถือได้ (สำหรับการจำลอง lockstep)
Kromster พูดว่าสนับสนุน Monica

5
ใช้ TCP เมื่อต้องการความน่าเชื่อถือใช้ UDP เมื่อไม่สำคัญ ตัวอย่างเช่นพิกัดของผู้เล่นจะถูกส่งในเกมของฉันผ่านทาง UDP ฉันใช้การแก้ไข & การปรับให้เรียบเพื่อทำให้แพ็กเก็ตที่หายไปหายไป ทำงานเหมือนจับใจ สิ่งที่ต้องมีความน่าเชื่อถือจริง ๆ แต่ช้าลงเล็กน้อยจะถูกส่งผ่าน TCP หากคุณมีสถานะที่ไม่มีรัฐที่ใหม่กว่าจะทำให้สถานะเดิมเป็นโมฆะ UDP เป็นตัวเลือกที่ดีเพราะมันไม่สำคัญว่าเมื่อมีสิ่งใดระหว่างอยู่ตก 8e.g ตำแหน่งผู้เล่น)
Polygnome

นี่ไม่ใช่คำตอบที่ตรงกับคำถามของคุณ แต่ฉันขอแนะนำอย่างยิ่งให้ต้องการการตอบรับในเกมเรียลไทม์เมื่อจำเป็นเท่านั้น (เช่นในการเชื่อมต่อครั้งแรก) มันง่ายกว่ามาก (และมีประสิทธิภาพ) ในการออกแบบทั้งไคลเอนต์และเซิร์ฟเวอร์เพื่อให้พวกเขา "ทำงานกับสิ่งที่พวกเขามี" จนกว่าพวกเขาจะได้รับแพ็คเก็ตใหม่ในระบบไร้สัญชาติถ้าคุณทำได้ Quake 3 ทำอย่างนี้ได้ดีอย่างเหลือเชื่อด้วยระบบภาพรวมตาม นอกจากนี้ยังมีห้องสมุดเหมือน Enet สามารถส่งแพ็คเก็ตมีเพียงบางอย่างน่าเชื่อถือสำหรับกรณีดังกล่าวเมื่อคุณต้องการจริงๆมัน
jrh

คำตอบ:


32

นี่เป็นรูปแบบของปัญหานายพลสองคนและคุณถูกต้อง - ไม่มีการลองซ้ำจำนวนมากพอที่จะรับประกันการรับได้อย่างสมบูรณ์แบบ

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

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

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

ทันใดนั้นฉันต้องการเริ่มเรียกสิ่งนี้ว่า "การจำลองแบบ Simba" โดยไม่สนใจปัญหาในอดีตและพยายามที่จะอยู่ในช่วงเวลาปัจจุบัน ;)

Rafiki วางแนวคิดที่ไร้สาระบางอย่างเกี่ยวกับปรัชญาชีวิต

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

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


1
+1 เขียนได้ดี ฉันจะเน้นว่านี่เกี่ยวข้องกับเกมแอ็คชั่น / เรียลไทม์มากขึ้น เกม TBS และ RTS (และกิจกรรมของเกมแอ็คชั่นบางอย่าง) มีมุมมองที่แตกต่างกันในเรื่อง "ระยะเวลาซึ่งข้อมูลไม่สำคัญ"
Kromster พูดว่าสนับสนุน Monica

3
ใช่สำหรับเกมเทิร์นเบสฉันคิดว่าใครจะใช้ TCP แทนที่จะลองใช้เลเยอร์ความน่าเชื่อถือของตนเองที่ด้านบนของ UDP ;) ฉันยังคงเรียนไมโครใน RTS เป็นประเภทของการเล่นเกมที่มีเส้นขอบฟ้าเวลาที่กำหนดแม้ว่า - วิธีไฮบริดที่อาจทำได้ดีที่นั่นที่คุณมีทั้งการปรับปรุงเวลาแฝงต่ำสำหรับความร้อนของเวลาและ เครือข่ายความปลอดภัยเพื่อย้อนหลังจัดการเหตุการณ์สำคัญที่ไม่ได้รับเช่นการใช้ทรัพยากร
DMGregory

นั่นเป็นประโยชน์อย่างมากและเป็นการตรวจสอบความกังวลเริ่มต้นของฉัน ขอบคุณมาก.
Grimelios

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

@Malters ฉันจะบอกว่ามันคุ้มค่าอย่างละเอียดในคำตอบของตัวเองถ้าคุณพร้อม ฉันต้องการโหวตว่า :)
DMGregory

9

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

หากแพ็กเก็ตสูญหายผู้ส่งจะส่งซ้ำตามที่คุณรู้อยู่แล้ว
หากการตอบรับสูญหายผู้ส่งจะส่งแพ็กเก็ตดั้งเดิมซึ่งทำให้ผู้รับรับส่งการตอบรับอีกครั้ง

หากไม่ได้รับการตอบรับภายในเวลาที่กำหนด (อาจเป็น 60 วินาทีหรือลองอีก 20 ครั้ง) ผู้เล่นจะถูกตัดการเชื่อมต่อจากเกม คุณต้องใช้กฎการหมดเวลาบางอย่างมิฉะนั้นผู้เล่นที่ถอดสายเคเบิลเครือข่ายจะผูกทรัพยากรบนเซิร์ฟเวอร์ของคุณตลอดไป


คุณลักษณะที่สำคัญของ TCP คือการที่ผู้ส่งไม่จำเป็นต้องดูแลเกี่ยวกับว่าใด ๆโดยเฉพาะอย่างยิ่งแพ็คเก็ตได้รับการยอมรับ แต่ส่วนใหญ่ต้องการที่จะดูแลเกี่ยวกับ "เครื่องหมายน้ำสูง" และวิธีการแพ็คเก็ตยาวได้รับการที่โดดเด่นโดยไม่ต้องสูงน้ำเครื่องหมายเคลื่อนไหว
supercat

1
@supercat ฉันจะไม่บอกว่าจำเป็น มากขึ้นเช่นการเพิ่มประสิทธิภาพ
user253751

เกี่ยวกับสิ่งที่อยู่ในวงเล็บ (การส่ง ACK สำหรับแพ็คเก็ตที่คุณมีอยู่แล้ว) ฉันคิดว่าคุณควรเน้นมันแทนการวงเล็บ ดูเหมือนว่าจะหายไปจากความเข้าใจของ OP (หรืออย่างน้อยก็คำอธิบาย)
Angew ไม่ภูมิใจใน SO

@ เสร็จแล้วตอนนี้
253751

6

หากคุณต้องการบูรณาการ TCP อีกครั้งคุณควรดูที่ TCPก่อนซึ่งเกี่ยวข้องกับปัญหาที่แน่นอนที่คุณอธิบาย

โซลูชันที่ใช้ 2 ช่องสัญญาณช่อง TCP (สำหรับการสื่อสารที่เชื่อถือได้) เช่นเดียวกับช่องสัญญาณ UDP (สำหรับการสื่อสารที่มีความหน่วงต่ำ) ไม่ใช่เรื่องแปลก

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

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


3

ใน RTS คุณไม่สามารถใช้โปรโตคอลเช่น TCP และคุณไม่สามารถทำให้ UDP เชื่อถือได้ หากคุณพยายามที่จะเกมจะหยุดเมื่อใดก็ตามที่มีเครือข่าย hick-up

แต่คุณออกแบบโปรโตคอลเพื่อให้แพ็กเก็ตที่ไม่ได้รับมีความสำคัญมาก

เวอร์ชั่นสั้นคือคุณไม่สนใจว่าผู้เล่นคนอื่นอยู่ที่เฟรมสุดท้ายตราบเท่าที่คุณรู้ว่าตอนนี้พวกเขาอยู่ที่ไหน รุ่นยาวซับซ้อนกว่า

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

นี่มันยาก. มีหลายเกมที่คิดผิด อาจเป็นที่ถกเถียงกันอยู่ว่าไม่มีคำตอบที่ถูกต้องในเรื่องนี้เฉพาะความผิดที่หลากหลายที่สามารถทำการค้าขายได้

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


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