คำเตือน
RNL รวมถึงรหัสการเข้ารหัสยังไม่ได้รับการตรวจสอบ ดังนั้น RNL จึงมีไว้สำหรับเกมแบบเรียลไทม์และแอปพลิเคชันมัลติมีเดียโดยไม่มีการประมวลผลข้อมูลใด ๆ ที่มีข้อมูลสำคัญ แต่ไม่ใช่สำหรับแอปพลิเคชันร้ายแรงที่มีข้อมูลสำคัญ!
คำอธิบาย
RNL ย่อมาจาก "ไลบรารีเครือข่ายเรียลไทม์"
RNL คือไลบรารีเครือข่ายที่ใช้ UDP สำหรับแอปพลิเคชันและเกมแบบเรียลไทม์ ซึ่งได้รับแรงบันดาลใจจาก ENet, yojimbo, libgren และอื่นๆ
RNL ได้รับการออกแบบโดยใช้รูปแบบทั่วไปที่ใช้ในเกมแบบเรียลไทม์ ซึ่งเป็นขอบเขตของการจำลอง ไม่ใช่ขอบเขตของ I/O และมีสถานะโดยสมบูรณ์ ดังนั้น async IO จึงไม่สมเหตุสมผลมากนัก ดังนั้นการออกแบบคอร์ RNL จึงเป็นแบบเธรดเดียว ไม่ใช่แบบมัลติเธรด แต่คุณสามารถใช้อินสแตนซ์ TRNLHost หลายรายการภายในเธรดที่แตกต่างกันหลายรายการได้ (อินสแตนซ์หนึ่งถึงน้อยมากต่อหนึ่งเธรด) เพื่อให้คุณสามารถโฮสต์การแข่งขันเกมบนเครือข่ายหลายรายการในเครื่องเดียวกันได้ ตราบใดที่เครื่องนี้แข็งแกร่งและรวดเร็วเพียงพอสำหรับการโฮสต์หลายรายการ การแข่งขันเกมบนเครือข่ายในเวลาเดียวกัน
และที่ฝั่งไคลเอนต์เกม หากเป็นไปได้ เนื้อหาในเครือข่ายทั้งหมดควรทำงานบนเธรดของตัวเอง (หรือหากเป็นไปได้ จะต้องปักหมุด CPU ไว้ด้วย) เพื่อไม่ให้เกิดการรบกวนและปัญหาอื่น ๆ ที่คล้ายกัน (นอกหัวข้อ: เช่นเดียวกับเธรดเสียง เว้นแต่ว่ามีคนชอบปัญหาบัฟเฟอร์เสียงที่เป็นไปได้ที่ด้อยลงและอื่น ๆ เมื่อได้รับเวลา CPU ไม่เพียงพอ ณ จุดเวลาที่เหมาะสม :-))
และสำหรับเกมขนาดใหญ่ที่มีไคลเอนต์จำนวนมากในโลกของเกมเดียว คุณควรใช้อินสแตนซ์ TRNLHost ที่แบ่งย่อยหลายอินสแตนซ์ เพื่อให้ TRNLHost แต่ละตัวต้องจัดการไคลเอนต์ที่เชื่อมต่อเพียงไม่กี่ไคลเอนต์ในหลายเธรด และในทางกลับกันบนเซิร์ฟเวอร์เฉพาะทางกายภาพหลายตัว ซึ่งในทางกลับกัน อาจสื่อสารกันเพื่อเลียนแบบความประทับใจของโลกเกมที่ใหญ่โตเพียงแห่งเดียว อย่างน้อยอินสแตนซ์ TRNLHost เดียวค่อนข้างได้รับการออกแบบมาสำหรับลูกค้าทั่วไปที่มีจำนวนน้อย เนื่องจากเป็นกรณีทั่วไปสำหรับนักยิงปืนอัตตานิยม เกมแข่งรถ และอื่นๆ หรืออีกนัยหนึ่งสำหรับโลกเกมขนาดใหญ่ที่มีลูกค้าจำนวนมาก: แบ่งและพิชิต (เช่น แบ่งเขตโลกของเกมที่ทับซ้อนกันบางส่วนเป็นขอบเขต เพื่อเป็นตัวอย่างของแนวคิดแนวคิดแบ่งแยกและพิชิต)
สนับสนุนฉัน
สนับสนุนผมได้ที่ Patreon
คุณสมบัติ
- การออกแบบโค้ดเชิงวัตถุส่วนใหญ่อย่างสมบูรณ์
- รองรับ IPv6
- ข้ามแพลตฟอร์ม
- Windows (พร้อม FreePascal และ Delphi)
- ลินุกซ์ (พร้อม FreePascal)
- *BSD (พร้อม FreePascal)
- Android (พร้อม FreePascal และ Delphi)
- ดาร์วิน (MacOS(X) และ iOS) (พร้อม FreePascal และ Delphi)
- โปรโตคอลที่ใช้ UDP
- การเรียงลำดับ
- ช่อง
- ด้วยประเภทช่องสัญญาณที่กำหนดค่าได้ฟรีที่เป็นไปได้ดังต่อไปนี้:
- สั่งได้เชื่อถือได้
- เชื่อถือได้ไม่มีการสั่งซื้อ
- สั่งแล้วไม่น่าเชื่อถือ
- ไม่น่าเชื่อถือไม่มีการสั่งซื้อ
- ความน่าเชื่อถือ
- การกระจายตัวและการประกอบกลับคืน
- การรวมกลุ่ม
- ความสามารถในการปรับตัว
- การพกพา
- ความเป็นไปได้ของการใช้โมเดลเพียร์ทูเพียร์ หรือแม้แต่โมเดลไฮบริดเพียร์ทูเพียร์และไคลเอนต์/เซิร์ฟเวอร์แบบผสม แทนเฉพาะโมเดลไคลเอนต์/เซิร์ฟเวอร์ล้วนๆ และแน่นอนว่ายังเป็นโมเดลไคลเอนต์/เซิร์ฟเวอร์แบบคลาสสิกด้วย
- ตัวสร้างตัวเลขสุ่มหลอกที่ปลอดภัยด้วยการเข้ารหัส (CSPRNG)
- อิงจาก arc4random แต่ใช้ ChaCha20 แทน RC4 เป็นตัวสร้างพื้นฐาน
- แหล่งเอนโทรปีหลายแห่ง (เพราะคุณไม่ควรเชื่อถือแหล่งเอนโทรปีแหล่งเดียว เนื่องจากอาจมีประตูหลัง)
- รวมถึงการใช้คำสั่ง rdseed/rdrand บนโปรเซสเซอร์ x86 รุ่นใหม่เป็นแหล่งเอนโทรปีที่ใช้กึ่งฮาร์ดแวร์เพิ่มเติม หากคำแนะนำเหล่านี้ได้รับการสนับสนุนโดยโปรเซสเซอร์ที่ทำงานอยู่ในปัจจุบัน
- การรับรองความถูกต้องร่วมกัน
- ขึ้นอยู่กับโปรโตคอลแบบ Station-to-Station (STS) ซึ่งถือว่าทั้งสองฝ่ายมีคีย์ลายเซ็นซึ่งใช้ในการลงนามข้อความ จึงให้การรักษาความปลอดภัยที่ลดขนาดลงจากการโจมตีแบบคนกลาง ซึ่งแตกต่างจาก Diffie ธรรมดาพื้นฐาน วิธี Hellman ที่ไม่มีส่วนขยายดังกล่าว
- คีย์ส่วนตัว/สาธารณะระยะยาวคือคีย์ ED25519 และใช้เพื่อวัตถุประสงค์ในการลงนามเท่านั้น
- ส่งต่อความลับโดยใช้เส้นโค้งวงรีชั่วคราว Diffie-Hellman (เส้นโค้ง 25519)
- ผลที่ตามมาของสิ่งนี้พร้อมกับข้อเท็จจริงอื่น ๆ ก็คือแต่ละการเชื่อมต่อจะมีคีย์ระยะสั้นส่วนตัวและสาธารณะที่แตกต่างกันอยู่เสมอทั้งสองด้าน และด้วยเหตุนี้จึงมีคีย์ระยะสั้นที่เป็นความลับใหม่ที่ใช้ร่วมกันด้วย
- คีย์ส่วนตัว/สาธารณะระยะสั้นคือคีย์ X25519 และคีย์ลับที่ใช้ร่วมกันระยะสั้นใช้เพื่อวัตถุประสงค์ในการเข้ารหัสตาม AEAD เท่านั้น
- การเข้ารหัสลับรับรองความถูกต้องด้วยการเข้ารหัสแพ็กเก็ตข้อมูลที่เกี่ยวข้อง (AEAD)
- ยึดตาม ChaCha20 เป็นรหัส และ Poly1305 เป็นรหัสตรวจสอบข้อความที่เข้ารหัส
- การป้องกันการเล่นซ้ำของข้อมูลแพ็กเก็ตแอปพลิเคชัน
- ขึ้นอยู่กับกลไกการป้องกันต่างๆ ในขั้นตอนการสร้างการเชื่อมต่อและหมายเลขลำดับแพ็กเก็ตที่เข้ารหัส
- กลไกการสร้างการเชื่อมต่อที่ล่าช้าเป็นกลไกการลดขนาดพื้นผิวการโจมตีเพิ่มเติม
- โทเค็นการเชื่อมต่อและการรับรองความถูกต้อง (เป็นตัวเลือกเสริม ซึ่งคุณควรมีช่องทางการสื่อสารนอกแบนด์แยกต่างหาก เช่น แบ็กเอนด์หลักที่ใช้ HTTPS สำหรับสร้างและจัดการสิ่งนี้) เป็นกลไกลดขนาดพื้นผิวการโจมตีเพิ่มเติมเพื่อต่อต้านการขยาย DDoS การโจมตี
- โทเค็นการเชื่อมต่อจะถูกถ่ายโอนเป็นข้อความที่ชัดเจน เพื่อให้ได้รับการตรวจสอบอย่างรวดเร็วในแพ็กเก็ตข้อมูลครั้งแรกจากความพยายามในการเชื่อมต่อ โดยไม่จำเป็นต้องถอดรหัสโทเค็นการเชื่อมต่อก่อน จึงจะสามารถตรวจสอบโทเค็นได้ ดังนั้นเพื่อที่จะ ประหยัดเวลา CPU ในจุดนี้ ตัวเลือกนี้มีไว้เพื่อใช้ต่อต้านการโจมตีแบบขยาย DDoS เป็นหลัก ซึ่งหมายความว่าเซิร์ฟเวอร์จะไม่ตอบสนองทันทีหากโทเค็นการเชื่อมต่อไม่ตรงกับแพ็กเก็ตข้อมูลครั้งแรกจากความพยายามในการเชื่อมต่อ ดังนั้นการโจมตีแบบขยาย DDoS จะเข้าสู่ ไม่มีอะไร. ด้วยเหตุนี้ โทเค็นเหล่านี้จึงควรใช้งานได้ในช่วงเวลาสั้นๆ เท่านั้น ซึ่งใช้กับแบ็คเอนด์หลักของโครงสร้างพื้นฐานของคุณด้วย
- โทเค็นการตรวจสอบสิทธิ์จะถูกถ่ายโอนแบบเข้ารหัส หลังจากที่การแลกเปลี่ยนคีย์ส่วนตัว/สาธารณะ การสร้างคีย์ลับที่แชร์ ฯลฯ ได้รับการประมวลผลสำเร็จ โทเค็นการรับรองความถูกต้องตรงกันข้ามกับโทเค็นการเชื่อมต่อ ไม่ใช่มาตรการตอบโต้การโจมตีประเภท DDoS แต่เป็นโทเค็นการรับรองความถูกต้องตามชื่อที่แนะนำ เพียงเพื่อวัตถุประสงค์ในการรับรองความถูกต้องของช่องทางการสื่อสารนอกแบนด์ที่แยกจากกันเท่านั้น กล่าวอีกนัยหนึ่ง เป็นส่วนเสริม ป้องกันการเชื่อมต่อที่ไม่ได้รับอนุญาต ซึ่งคุณสามารถตรวจสอบรายละเอียดเพิ่มเติมได้ที่ฝั่งแบ็กเอนด์หลักของโครงสร้างพื้นฐานของคุณ ก่อนที่ "ไคลเอนต์" จะสามารถเชื่อมต่อกับเซิร์ฟเวอร์จริง ซึ่งเป็นที่ที่การกระทำจริงทั้งหมดเกิดขึ้น
- ตัวจำกัดอัตราความพยายามในการเชื่อมต่อ
- กำหนดค่าได้ด้วยค่าคงที่สองค่า ต่อเนื่องและช่วงเวลา
- ตัวจำกัดอัตราแบนด์วิธที่กำหนดค่าได้
- คุณสมบัติเครือข่ายเสมือนเสริม (เช่น สำหรับโซลูชันลูปแบ็คภายในแบบไร้เครือข่าย API ที่รวดเร็วสำหรับการแข่งขันเกมผู้เล่นคนเดียว ซึ่งควรจะยังคงเป็นแนวคิดของเซิร์ฟเวอร์/ไคลเอ็นต์)
- เครื่องจำลองการรบกวนเครือข่าย (เช่น กรณีทดสอบ และอื่นๆ)
- ความน่าจะเป็นของการสูญเสียแพ็กเก็ตจำลองที่กำหนดค่าได้ (แต่ละอันสำหรับแพ็กเก็ตขาเข้าและขาออก)
- เวลาแฝงจำลองที่กำหนดค่าได้ (แต่ละอันสำหรับแพ็กเก็ตขาเข้าและขาออก)
- ความกระวนกระวายใจจำลองที่กำหนดค่าได้ (แต่ละอันสำหรับแพ็กเก็ตขาเข้าและขาออก)
- ความน่าจะเป็นของแพ็กเก็ตจำลองที่กำหนดค่าได้ (แต่ละอันสำหรับแพ็กเก็ตขาเข้าและขาออก)
- กลไกการปรับความยากลำบากในการตอบสนองคำขอการเชื่อมต่อแบบไดนามิก
- กำหนดค่าได้ด้วยค่าตัวประกอบ
- ขึ้นอยู่กับกลไกการกำหนดรูปแบบประวัติที่ราบรื่นเฟรมต่อวินาที แต่เพียงเฟรมต่อวินาทีความพยายามในการเชื่อมต่อต่อวินาทีแทน
- อัลกอริธึมการบีบอัดเพิ่มเติมเป็นตัวเลือก
- Deflate (LZ77 ที่เข้ากันได้กับ zlib bit-stream และไฮบริด Canonical Huffman เฉพาะแบบคงที่แบบคงที่-canonical-huffman ในการใช้งานนี้ที่ด้านคอมเพรสเซอร์ แต่ด้านตัวขยายการบีบอัดนั้นมีคุณลักษณะครบถ้วน)
- LZBRRC (คอมเพรสเซอร์แบบ LZ77 พร้อมด้วยแบ็กเอนด์โค้ดเดอร์ช่วงเอนโทรปี)
- BRRC (ตัวเข้ารหัสช่วงเอนโทรปีลำดับ 0 ล้วนๆ)
- CRC32C แทน CRC32 (ไม่มี C ในตอนท้าย)
- และของอื่นๆอีกมากมาย - -
คุณสมบัติที่วางแผนไว้ (หรือที่เรียกว่า Todo) ตามลำดับลำดับความสำคัญแบบสุ่ม
แนวทางทั่วไปสำหรับผู้ร่วมเขียนโค้ด
แนวทางทั่วไปสำหรับผู้ร่วมเขียนโค้ด
ใบอนุญาต
ใบอนุญาต zlib
ช่องไออาร์ซี
ช่อง IRC #rnl บน Freenode
ขอบคุณ
- ขอขอบคุณ Lee Salzman สำหรับ ENet ที่เป็นแรงบันดาลใจสำหรับแนวคิดการใช้งานการออกแบบ API พื้นฐาน
- ขอขอบคุณ Glenn Fiedler สำหรับแรงบันดาลใจสำหรับแนวคิดการใช้งานที่มุ่งเน้นด้านความปลอดภัย
- ขอขอบคุณ Sergey Ignatchenko ("No Bugs" Hare) สำหรับแรงบันดาลใจสำหรับแนวคิดการใช้งานที่เน้นความปลอดภัย