อ่านข้อมูลเป็นภาษาอังกฤษ
KCP เป็นโปรโตคอลที่รวดเร็วและเชื่อถือได้ซึ่งสามารถลดความล่าช้าโดยเฉลี่ยได้ 30%-40% และลดความล่าช้าสูงสุดได้ 3 เท่า โดยมีต้นทุนแบนด์วิธมากกว่า TCP 10%-20% การใช้อัลกอริธึมที่แท้จริงจะไม่รับผิดชอบต่อการส่งและรับโปรโตคอลพื้นฐาน (เช่น UDP) ผู้ใช้จำเป็นต้องกำหนดวิธีการส่งของแพ็กเก็ตข้อมูลชั้นล่างและจัดเตรียมให้กับ KCP ในรูปแบบของการโทรกลับ แม้แต่นาฬิกาก็ยังจำเป็นต้องส่งผ่านเข้าไปภายนอก และจะไม่มีการเรียกระบบใดๆ ภายใน
โปรโตคอลทั้งหมดมีไฟล์ต้นฉบับเพียงสองไฟล์เท่านั้น ได้แก่ ikcp.h และ ikcp.c ซึ่งสามารถรวมเข้ากับสแต็กโปรโตคอลของผู้ใช้ได้อย่างง่ายดาย บางทีคุณอาจใช้ P2P หรือโปรโตคอลที่ใช้ UDP แต่ขาดการใช้งานโปรโตคอล ARQ ที่สมบูรณ์และเชื่อถือได้ จากนั้นเพียงคัดลอกไฟล์ทั้งสองนี้ไปยังโปรเจ็กต์ที่มีอยู่ เขียนโค้ดสองสามบรรทัด แล้วคุณก็จะสามารถใช้งานได้
TCP ได้รับการออกแบบมาสำหรับการรับส่งข้อมูล (สามารถส่งข้อมูลได้กี่ KB ต่อวินาที) และเน้นไปที่การใช้แบนด์วิดท์อย่างเต็มที่ KCP ได้รับการออกแบบมาสำหรับอัตราการไหล (ระยะเวลาในการส่งแพ็กเก็ตข้อมูลเดียวจากปลายด้านหนึ่งไปยังอีกปลายหนึ่ง) โดยจะแลกเปลี่ยนแบนด์วิธที่เสียไป 10%-20% สำหรับความเร็วในการส่งข้อมูลที่เร็วกว่า TCP 30%-40% . ช่อง TCP เป็นช่องขนาดใหญ่ที่มีอัตราการไหลช้าแต่มีอัตราการไหลต่อวินาทีสูง ในขณะที่ช่อง KCP จะเป็นช่องแคบขนาดเล็กที่มีการไหลเร็ว KCP มีสองประเภท: โหมดปกติและโหมดเร็ว ผลลัพธ์ของการเพิ่มอัตราการไหลทำได้โดยใช้กลยุทธ์ต่อไปนี้:
การคำนวณการหมดเวลา TCP คือ RTOx2 หากคุณสูญเสียแพ็กเก็ตสามรายการติดต่อกัน มันจะกลายเป็น RTOx8 ซึ่งน่ากลัวมาก อย่างไรก็ตาม หลังจากที่ KCP เริ่มโหมดเร็ว มันจะไม่ใช่ x2 แต่มีเพียง x1.5 เท่านั้น (การทดลองได้พิสูจน์แล้วว่า ค่า 1.5 ค่อนข้างดี) ซึ่งช่วยเพิ่มความเร็วในการส่งข้อมูล
เมื่อ TCP สูญเสียแพ็กเก็ต มันจะส่งข้อมูลทั้งหมดอีกครั้งโดยเริ่มจากแพ็กเก็ตที่สูญหาย KCP จะส่งซ้ำแบบเลือกและส่งเฉพาะแพ็กเก็ตข้อมูลที่สูญหายอย่างแท้จริงเท่านั้น
ผู้ส่งส่งแพ็กเก็ต 1, 2, 3, 4 และ 5 หลายแพ็กเก็ต และรับ ACK จากระยะไกล: 1, 3, 4, 5 เมื่อได้รับ ACK3 KCP รู้ว่า 2 ถูกข้ามหนึ่งครั้ง และได้รับเมื่อ ACK4 ได้รับเป็นที่ทราบกันว่าแพ็กเก็ตหมายเลข 2 ถูกข้ามไปสองครั้ง ในเวลานี้ ถือว่าแพ็กเก็ตหมายเลข 2 หายไป ไม่จำเป็นต้องรอจนหมดเวลาและสามารถส่งแพ็กเก็ตหมายเลข 2 ใหม่ได้โดยตรง ซึ่งจะช่วยปรับปรุงอย่างมาก ความเร็วในการส่งข้อมูลเมื่อแพ็กเก็ตสูญหาย
เพื่อที่จะใช้แบนด์วิดท์อย่างเต็มที่ TCP จะหน่วงเวลาการส่ง ACK (NODELAY ไม่มีประโยชน์) ด้วยวิธีนี้ การคำนวณการหมดเวลาจะคำนวณเวลา RTT ที่มากขึ้น ซึ่งจะทำให้กระบวนการตัดสินยืดเยื้อเมื่อแพ็กเก็ตสูญหาย คุณสามารถปรับเปลี่ยนได้ว่า ACK ของ KCP จะถูกส่งล่าช้าหรือไม่
การตอบกลับโมเดล ARQ มีสองประเภท ได้แก่ UNA (แพ็กเก็ตทั้งหมดก่อนได้รับหมายเลขนี้ เช่น TCP) และ ACK (ได้รับแพ็กเก็ตที่มีหมายเลขนี้) การใช้ UNA เพียงอย่างเดียวจะทำให้เกิดการส่งสัญญาณซ้ำทั้งหมด ในขณะที่การใช้ ACK เพียงอย่างเดียวจะทำให้เกิดการส่งซ้ำ ต้นทุนการสูญเสียสูงเกินไป ในอดีต โปรโตคอลทั้งหมดเกี่ยวกับการเลือกหนึ่งในสองโปรโตคอล แต่ในโปรโตคอล KCP ยกเว้นแพ็กเก็ต ACK เดี่ยว แพ็กเก็ตทั้งหมดมีข้อมูล UNA
โหมดปกติของ KCP ใช้กฎสัมปทานที่ยุติธรรมเช่นเดียวกับ TCP นั่นคือขนาดหน้าต่างการส่งจะถูกกำหนดโดยปัจจัยสี่ประการ: ขนาดบัฟเฟอร์การส่ง ขนาดบัฟเฟอร์การรับที่เหลือที่ส่วนรับ สัมปทานการสูญเสียแพ็กเก็ต และการเริ่มต้นช้า อย่างไรก็ตาม เมื่อส่งข้อมูลขนาดเล็กที่มีข้อกำหนดด้านเวลาสูง คุณสามารถเลือกที่จะข้ามสองขั้นตอนสุดท้ายผ่านการกำหนดค่า และใช้เพียงสองรายการแรกเพื่อควบคุมความถี่ในการส่ง ด้วยค่าใช้จ่ายของความเป็นธรรมบางส่วนและการใช้แบนด์วิธ ผลของการรับส่งข้อมูลที่ราบรื่นสามารถทำได้แม้ในขณะที่เปิด BT ก็ตาม
คุณสามารถดาวน์โหลดและติดตั้ง kcp ได้โดยใช้ตัวจัดการไลบรารี vcpkg:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install kcp
ไลบรารี kcp ใน vcpkg ได้รับการปรับปรุงให้ทันสมัยโดยสมาชิกทีม Microsoft และผู้สนับสนุนชุมชน หากเวอร์ชันล้าสมัย โปรดสร้างปัญหาหรือยกระดับ PR บนที่เก็บ vcpkg
สร้างวัตถุ KCP:
// 初始化 kcp对象,conv为一个表示会话编号的整数,和tcp的 conv一样,通信双
// 方需保证 conv相同,相互的数据包才能够被认可,user是一个给回调函数的指针
ikcpcb *kcp = ikcp_create(conv, user);
ตั้งค่าฟังก์ชันโทรกลับ:
// KCP的下层协议输出函数,KCP需要发送数据时会调用它
// buf/len 表示缓存和长度
// user指针为 kcp对象创建时传入的值,用于区别多个 KCP对象
int udp_output ( const char *buf, int len, ikcpcb *kcp, void *user)
{
....
}
// 设置回调函数
kcp->output = udp_output;
อัปเดตการโทรแบบวนซ้ำ:
// 以一定频率调用 ikcp_update来更新 kcp状态,并且传入当前时钟(毫秒单位)
// 如 10ms调用一次,或用 ikcp_check确定下次调用 update的时间不必每次调用
ikcp_update (kcp, millisec);
ป้อนแพ็กเก็ตชั้นล่าง:
// 收到一个下层数据包(比如UDP包)时需要调用:
ikcp_input (kcp, received_udp_packet, received_udp_size);
หลังจากประมวลผลเอาต์พุต/อินพุตของโปรโตคอลชั้นล่างแล้ว โปรโตคอล KCP สามารถทำงานได้ตามปกติ ใช้ ikcp_send เพื่อส่งข้อมูลไปยังปลายทางระยะไกล ปลายอีกด้านหนึ่งใช้ ikcp_recv(kcp, ptr, size) เพื่อรับข้อมูล
โหมดเริ่มต้นของโปรโตคอลคือ ARQ มาตรฐาน และจำเป็นต้องเปิดสวิตช์เร่งความเร็วต่างๆ ผ่านการกำหนดค่า:
โหมดการทำงาน:
int ikcp_nodelay (ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
หน้าต่างสูงสุด:
int ikcp_wndsize (ikcpcb *kcp, int sndwnd, int rcvwnd);
การโทรนี้จะตั้งค่าหน้าต่างการส่งสูงสุดและขนาดหน้าต่างการรับสูงสุดของโปรโตคอล ซึ่งมีค่าเริ่มต้นอยู่ที่ 32 ซึ่งสามารถเข้าใจได้ว่าเป็น SND_BUF และ RCV_BUF ของ TCP แต่หน่วยจะแตกต่างกัน หน่วย SND/RCV_BUF เป็นไบต์ และหน่วยนี้คือ แพ็กเก็ต
หน่วยส่งกำลังสูงสุด:
โปรโตคอลอัลกอริธึมบริสุทธิ์ไม่รับผิดชอบในการตรวจจับ MTU mtu เริ่มต้นคือ 1400 ไบต์ คุณสามารถใช้ ikcp_setmtu เพื่อตั้งค่านี้ได้ ค่านี้จะส่งผลต่อหน่วยการส่งข้อมูลสูงสุดเมื่อรวมและแยกส่วนแพ็กเก็ตข้อมูล
RTO ขั้นต่ำ:
ไม่ว่าจะเป็น TCP หรือ KCP มีขีดจำกัด RTO ขั้นต่ำเมื่อคำนวณ RTO แม้ว่า RTO ที่คำนวณได้จะเป็น 40ms เนื่องจาก RTO เริ่มต้นคือ 100ms โปรโตคอลจึงสามารถตรวจจับการสูญเสียแพ็กเก็ตหลังจาก 100ms เท่านั้น ในโหมดเร็ว จะเป็น 30ms ค่านี้สามารถเปลี่ยนแปลงได้ด้วยตนเอง
kcp->rx_minrto = 10 ;
การใช้งานและการกำหนดค่าโปรโตคอลนั้นง่ายมาก ในกรณีส่วนใหญ่ คุณสามารถใช้งานได้หลังจากอ่านเนื้อหาข้างต้นแล้ว หากคุณต้องการการควบคุมแบบละเอียดเพิ่มเติม เช่น การเปลี่ยนตัวจัดสรรหน่วยความจำของ KCP หรือคุณต้องการกำหนดเวลาการเชื่อมต่อ KCP ในขนาดใหญ่อย่างมีประสิทธิภาพมากขึ้น (เช่น มากกว่า 3,500) หรือวิธีผสานรวมกับ TCP ได้ดีขึ้น คุณก็สามารถทำได้ อ่านต่อ:
การอ่านที่เกี่ยวข้อง: "Genshin Impact" ยังใช้ KCP เพื่อเร่งข่าวสารเกม
KCP ประสบความสำเร็จในการดำเนินโครงการหลายโครงการโดยมีผู้ใช้หลายร้อยล้านราย มอบประสบการณ์เครือข่ายที่ตอบสนองและราบรื่นยิ่งขึ้น
ยินดีต้อนรับสู่การบอกเรากรณีเพิ่มเติม
หากเครือข่ายไม่เคยติดขัด KCP/TCP จะทำงานคล้ายกัน แต่ตัวเครือข่ายเองก็ไม่น่าเชื่อถือ และแพ็กเก็ตที่สูญหายและความกระวนกระวายใจเป็นสิ่งที่หลีกเลี่ยงไม่ได้ (ไม่เช่นนั้น เหตุใดเราจึงต้องมีโปรโตคอลที่เชื่อถือได้หลากหลาย) เมื่อเปรียบเทียบโดยตรงในสภาพแวดล้อมที่เกือบจะสมบูรณ์แบบ เช่น อินทราเน็ต ทุกคนเกือบจะเหมือนกัน อย่างไรก็ตาม เมื่อวางไว้บนเครือข่ายสาธารณะ วางบนเครือข่าย 3G/4G หรือใช้การจำลองการสูญเสียแพ็กเก็ตอินทราเน็ต ช่องว่างจะชัดเจน เครือข่ายสาธารณะมีการสูญเสียแพ็กเก็ตโดยเฉลี่ยเกือบ 10% ในช่วงที่มีการใช้งานสูงสุด และแย่กว่านั้นหากใช้ WiFi/3g/4g ซึ่งจะทำให้การส่งข้อมูลล่าช้า
ขอขอบคุณ zhangyuan ผู้เขียน asio-kcp สำหรับการประเมินแนวนอนของ KCP, enet และ udt ข้อสรุปมีดังนี้:
สำหรับรายละเอียด โปรดดูที่: ข้อมูลการเปรียบเทียบและการประเมินแนวนอนให้คำแนะนำเพิ่มเติมสำหรับผู้ที่ลังเลที่จะเลือก
เอ็นจิ้นเซิร์ฟเวอร์เกมผู้เล่นหลายคนขนาดใหญ่ SpatialOS ทำการประเมินเช่นเดียวกับ TCP/RakNet หลังจากรวมโปรโตคอล KCP:
เราเปรียบเทียบเวลาตอบสนองเมื่อรักษา 50 ตัวอักษรในเวลาเดียวกันกับอัตราการรีเฟรช 60 Hz บนฝั่งเซิร์ฟเวอร์ โปรดดูรายงานการเปรียบเทียบโดยละเอียด:
ในช่วงไม่กี่ปีที่ผ่านมา เกมออนไลน์และโซเชียลเน็ตเวิร์กต่างๆ เติบโตขึ้นอย่างก้าวกระโดด ไม่ว่าจะเป็นเกมออนไลน์หรือโซเชียลเน็ตเวิร์กแบบโต้ตอบต่างๆ ก็ตาม การโต้ตอบและความซับซ้อนก็เพิ่มขึ้นอย่างรวดเร็ว และทั้งหมดจำเป็นต้องส่งข้อมูลพร้อมกันในระยะเวลาอันสั้น ของผู้ใช้ เทคโนโลยีการส่งข้อมูลจะกลายเป็นปัจจัยสำคัญที่จำกัดการพัฒนาในอนาคตโดยธรรมชาติ และโปรโตคอลการส่งข้อมูลต่างๆ ที่รู้จักกันดีในโลกโอเพ่นซอร์ส เช่น raknet/enet ตัวอย่างเช่น เมื่อมีการเผยแพร่ โปรโตคอลทั้งหมดจะถูกปล่อยออกมาพร้อมกัน แบบฟอร์มนี้ไม่เอื้อต่อการกระจายความเสี่ยง โปรเจ็กต์ของฉันสามารถเลือกได้ว่าจะใช้คุณหรือไม่เท่านั้น ชุดโปรโตคอลจะดีแค่ไหนก็ยากที่จะตอบสนองความต้องการที่หลากหลายจากมุมที่ต่างกัน
ดังนั้น วิธีการของ KCP คือการ "แยกส่วน" สแต็กโปรโตคอล เพื่อให้ทุกคนสามารถปรับและประกอบได้อย่างยืดหยุ่นตามความต้องการของโปรเจ็กต์ คุณสามารถเพิ่มเลเยอร์ของรหัสลบของ reed Solomon ด้านล่างสำหรับ FEC และเลเยอร์ด้านบนสำหรับ RC4/Salsa20 สำหรับการเข้ารหัสสตรีม การแลกเปลี่ยนคีย์แบบอสมมาตรได้รับการออกแบบเมื่อมีการจับมือกัน และระบบการกำหนดเส้นทางแบบไดนามิกจะถูกสร้างขึ้นที่เลเยอร์การขนส่ง UDP พื้นฐานเพื่อตรวจจับหลายเส้นทางในเวลาเดียวกัน และเลือกเส้นทางที่ดีที่สุดสำหรับการส่งข้อมูล "หน่วยโปรโตคอล" ที่แตกต่างกันเหล่านี้สามารถรวมกันได้อย่างอิสระตามต้องการ เช่น แบบเอกสารสำเร็จรูปเพื่อให้มั่นใจว่า "เรียบง่าย" และ "สามารถแยกออกได้" เพื่อให้สามารถปรับให้เข้ากับความต้องการทางธุรกิจที่เปลี่ยนแปลงไปได้อย่างยืดหยุ่น หากโมดูลใดไม่ดี เพียงแค่เปลี่ยนใหม่
โซลูชันการส่งข้อมูลในอนาคตจะต้องได้รับการปรับแต่งอย่างลึกซึ้งตามสถานการณ์การใช้งาน ดังนั้นเราจึงมอบ "หน่วยโปรโตคอล" แก่ทุกคนที่สามารถรวมเข้าด้วยกันได้อย่างอิสระเพื่ออำนวยความสะดวกในการรวมเข้ากับสแต็กโปรโตคอลของคุณเอง
สำหรับข้อมูลเพิ่มเติม โปรดดูเรื่องราวความสำเร็จ
ผู้แต่ง: หลินเหว่ย (skywind3000)
ยินดีต้อนรับสู่ติดตามฉันได้ที่: บล็อกส่วนตัวและ Twitter
จากประสบการณ์การพัฒนาหลายปีของฉัน ฉันชอบศึกษาและแก้ไขปัญหาคอขวดในโปรแกรมมาโดยตลอด ในช่วงปีแรก ๆ ฉันชอบการพัฒนาเกม ฉันติดตาม "การเขียนโปรแกรม VGA" เพื่อทำกราฟิกเกม และอ่าน "โปรแกรมกราฟิกของ Michael Abrash คู่มือนักพัฒนา" เพื่อทำการเรนเดอร์แบบนุ่มนวล ฉันชอบเล่นกับโค้ดบางตัวที่สามารถบีบ CPU และทำงานเร็วขึ้น หลังจากเข้าร่วมงาน ความสนใจของฉันก็เปลี่ยนไปใช้เทคโนโลยีฝั่งเซิร์ฟเวอร์และเครือข่าย
ในปี 2550 หลังจากสร้างเกมแบบดั้งเดิมมาหลายเกม ฉันเริ่มศึกษาปัญหาการซิงโครไนซ์ของเกมแอคชั่นที่รวดเร็ว ในช่วงเวลานี้ ฉันเขียนบทความมากมาย ฉันเป็นหนึ่งในคนกลุ่มแรก ๆ ในประเทศจีนที่ศึกษาปัญหาการซิงโครไนซ์ ไม่ว่าจะแก้ปัญหาการซิงโครไนซ์อย่างไรเราก็ต้องทำอะไรสักอย่างในแง่ของการส่งสัญญาณเครือข่าย หลังจากออกจากเกมและเปลี่ยนมาใช้อินเทอร์เน็ตฉันก็พบว่ามีหลายสาขาที่มีความต้องการนี้ดังนั้นฉันจึงเริ่มใช้เวลาไปกับการส่งสัญญาณเครือข่าย พยายามใช้โปรโตคอลที่อนุรักษ์นิยมและเชื่อถือได้โดยใช้ UDP และเลียนแบบโค้ดของ BSD Lite 4.4 เพื่อใช้ TCP บางอย่างที่เหมือนกัน ฉันพบว่ามันน่าสนใจทีเดียว จากนั้นจึงนำของเล่นบางอย่างที่เกี่ยวข้องกับ P2P และเครือข่ายการกำหนดเส้นทางแบบไดนามิกไปใช้ โปรโตคอล KCP เกิดในปี 2554 โดยพื้นฐานแล้วเป็นหนึ่งในของเล่นหลาย ๆ ชิ้นที่ผลิตด้วยตัวมันเองในแง่ของการส่งสัญญาณ
xtaci ผู้เขียน Kcptun คือเพื่อนร่วมชั้นในวิทยาลัยของฉัน เราเรียนเอกด้านการสื่อสารและเรามักจะศึกษาวิธีเพิ่มประสิทธิภาพการส่งสัญญาณร่วมกัน
ยินดีต้อนรับสู่การใช้ Alipay เพื่อสแกนโค้ด QR ด้านบนเพื่อบริจาคให้กับโครงการนี้ การบริจาคจะถูกนำมาใช้เพื่อเพิ่มประสิทธิภาพโปรโตคอล KCP และปรับปรุงเอกสารประกอบอย่างต่อเนื่อง
ขอขอบคุณ: Mingming, Xingzi, Jin, Fan, Yanzhao, Binquan, Xiaodan, Yu Zheng, Hu, Shenggan, Xu Wei, Wang Chuan, Zhao Gangqiang, Hu Zhifeng, Wan Xinchao, He Xinchao, Liu Yang, Hou Xianhui, Wu Peiyi , ฮัวปิน, รุเตา, หูเจียน - - (ขออภัยที่ไม่ได้บันทึกรายการก่อนหน้านี้) เรากำลังรอการบริจาคและการสนับสนุนจากเพื่อนร่วมชั้นอยู่
ยินดีให้ความสนใจ
กลุ่มการสื่อสาร KCP: 364933586 (หมายเลขกลุ่ม QQ), การรวม KCP, การปรับแต่ง, การส่งผ่านเครือข่าย และการสนทนาทางเทคนิคที่เกี่ยวข้อง
กลุ่ม Gitter: https://gitter.im/skywind3000/KCP
บล็อก: http://www.skywind.me
โครงการนี้เกิดขึ้นได้ต้องขอบคุณทุกคนที่มีส่วนร่วม