README auf Englisch
KCP ist ein schnelles und zuverlässiges Protokoll, das die durchschnittliche Verzögerung um 30–40 % und die maximale Verzögerung um das Dreifache reduzieren kann, allerdings auf Kosten von 10–20 % mehr Bandbreite als TCP. Die reine Algorithmusimplementierung ist nicht für das Senden und Empfangen der zugrunde liegenden Protokolle (z. B. UDP) verantwortlich. Benutzer müssen die Sendemethode für Datenpakete der unteren Ebene definieren und diese in Form eines Rückrufs an KCP bereitstellen. Sogar die Uhr muss extern übergeben werden und es erfolgt intern kein Systemaufruf.
Das gesamte Protokoll verfügt nur über zwei Quelldateien, ikcp.h und ikcp.c, die problemlos in den eigenen Protokollstapel des Benutzers integriert werden können. Vielleicht haben Sie ein P2P- oder ein UDP-basiertes Protokoll implementiert, aber es fehlt Ihnen eine vollständige und zuverlässige ARQ-Protokollimplementierung. Dann kopieren Sie einfach diese beiden Dateien in das bestehende Projekt, schreiben Sie ein paar Zeilen Code und Sie können es verwenden.
TCP ist für den Datenverkehr konzipiert (wie viele KB Daten können pro Sekunde übertragen werden) und der Schwerpunkt liegt auf der vollständigen Ausnutzung der Bandbreite. KCP ist auf die Flussrate ausgelegt (wie lange es dauert, bis ein einzelnes Datenpaket von einem Ende zum anderen gesendet wird). Es tauscht 10–20 % der Bandbreitenverschwendung gegen eine Übertragungsgeschwindigkeit aus, die 30–40 % schneller als TCP ist . Der TCP-Kanal ist ein großer Kanal mit einer langsamen Flussrate, aber einer großen Flussrate pro Sekunde, während der KCP-Kanal ein kleiner Kanal mit schnellem Fluss ist. Es gibt zwei Arten von KCP: Normalmodus und Schnellmodus. Das Ergebnis der Erhöhung der Durchflussrate wird durch die folgenden Strategien erreicht:
Die TCP-Timeout-Berechnung beträgt RTOx2. Wenn Sie drei Pakete hintereinander verlieren, wird es zu RTOx8, was sehr beängstigend ist. Nachdem KCP den Schnellmodus gestartet hat, beträgt es jedoch nicht x2, sondern nur x1,5 (Experimente haben dies bewiesen). der Wert von 1,5 ist relativ gut), was die Übertragungsgeschwindigkeit verbessert.
Wenn TCP ein Paket verliert, überträgt es alle Daten erneut, beginnend mit dem verlorenen Paket. KCP überträgt selektiv erneut und überträgt nur die wirklich verlorenen Datenpakete erneut.
Der Absender sendete mehrere Pakete 1, 2, 3, 4 und 5 und empfing dann das ACK vom entfernten Ende: 1, 3, 4, 5. Beim Empfang von ACK3 wusste KCP, dass 2 einmal übersprungen wurde, und empfing es beim Empfang von ACK4 Beim Empfang ist bekannt, dass Paket Nr. 2 zweimal übersprungen wurde. Zu diesem Zeitpunkt kann davon ausgegangen werden, dass Paket Nr. 2 verloren geht. Es besteht keine Notwendigkeit, auf die Zeitüberschreitung zu warten, und Paket Nr. 2 kann direkt erneut übertragen werden, was eine erhebliche Verbesserung darstellt die Übertragungsgeschwindigkeit bei Paketverlust.
Um die Bandbreite voll auszunutzen, verzögert TCP das Senden von ACK (NODELAY ist nutzlos). Auf diese Weise berechnet die Timeout-Berechnung eine längere RTT-Zeit, was den Beurteilungsprozess verlängert, wenn ein Paketverlust auftritt. Ob KCPs ACK verzögert gesendet wird, kann angepasst werden.
Es gibt zwei Arten von ARQ-Modellantworten: UNA (alle Pakete vor dieser Nummer wurden empfangen, z. B. TCP) und ACK (die Verwendung von UNA allein führt zu allen Neuübertragungen, während die Verwendung von ACK allein dazu führt). Zu hohe Verlustkosten. In der Vergangenheit ging es bei Protokollen nur darum, eines von beiden zu wählen, aber im KCP-Protokoll verfügen alle Pakete mit Ausnahme einzelner ACK-Pakete über UNA-Informationen.
Der normale KCP-Modus verwendet dieselbe faire Konzessionsregel wie TCP, d. h. die Größe des Sendefensters wird durch vier Faktoren bestimmt: die Größe des Sendepuffers, die verbleibende Empfangspuffergröße am Empfangsende, die Konzession für Paketverlust und den langsamen Start. Bei der Übertragung kleiner Datenmengen mit hohen Aktualitätsanforderungen können Sie jedoch die letzten beiden Schritte der Konfiguration überspringen und nur die ersten beiden Elemente zur Steuerung der Sendefrequenz verwenden. Auf Kosten der teilweisen Fairness und Bandbreitennutzung kann der Effekt einer reibungslosen Übertragung auch bei eingeschaltetem BT erreicht werden.
Sie können kcp mit dem vcpkg-Bibliotheksmanager herunterladen und installieren:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install kcp
Die kcp-Bibliothek in vcpkg wird von Microsoft-Teammitgliedern und Community-Mitwirkenden auf dem neuesten Stand gehalten. Wenn die Version veraltet ist, erstellen Sie bitte ein Problem oder erstellen Sie eine PR für das vcpkg-Repository.
KCP-Objekt erstellen:
// 初始化 kcp对象,conv为一个表示会话编号的整数,和tcp的 conv一样,通信双
// 方需保证 conv相同,相互的数据包才能够被认可,user是一个给回调函数的指针
ikcpcb *kcp = ikcp_create(conv, user);
Rückruffunktion festlegen:
// KCP的下层协议输出函数,KCP需要发送数据时会调用它
// buf/len 表示缓存和长度
// user指针为 kcp对象创建时传入的值,用于区别多个 KCP对象
int udp_output ( const char *buf, int len, ikcpcb *kcp, void *user)
{
....
}
// 设置回调函数
kcp->output = udp_output;
Rufen Sie das Update in einer Schleife auf:
// 以一定频率调用 ikcp_update来更新 kcp状态,并且传入当前时钟(毫秒单位)
// 如 10ms调用一次,或用 ikcp_check确定下次调用 update的时间不必每次调用
ikcp_update (kcp, millisec);
Geben Sie ein Paket der unteren Schicht ein:
// 收到一个下层数据包(比如UDP包)时需要调用:
ikcp_input (kcp, received_udp_packet, received_udp_size);
Nach der Verarbeitung der Ausgabe/Eingabe des Protokolls der unteren Schicht kann das KCP-Protokoll normal funktionieren. Verwenden Sie ikcp_send, um Daten an die Gegenstelle zu senden. Das andere Ende verwendet ikcp_recv (kcp, ptr, size), um Daten zu empfangen.
Der Standardmodus des Protokolls ist ein Standard-ARQ, und verschiedene Beschleunigungsschalter müssen über die Konfiguration aktiviert werden:
Arbeitsmodus:
int ikcp_nodelay (ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
Maximales Fenster:
int ikcp_wndsize (ikcpcb *kcp, int sndwnd, int rcvwnd);
Dieser Aufruf legt das maximale Sendefenster und die maximale Empfangsfenstergröße des Protokolls fest, die standardmäßig auf 32 eingestellt sind. Dies kann als SND_BUF und RCV_BUF von TCP verstanden werden, die Einheiten sind jedoch unterschiedlich. Die SND/RCV_BUF-Einheit ist Bytes, und diese Einheit ist es Pakete.
Maximale Übertragungseinheit:
Das reine Algorithmusprotokoll ist nicht für die Erkennung der MTU verantwortlich. Der Standard-MTU beträgt 1400 Byte. Sie können diesen Wert mit ikcp_setmtu festlegen. Dieser Wert beeinflusst die maximale Übertragungseinheit beim Kombinieren und Fragmentieren von Datenpaketen.
Mindest-RTO:
Unabhängig davon, ob es sich um TCP oder KCP handelt, gibt es bei der Berechnung des RTO einen minimalen RTO-Grenzwert. Da der Standard-RTO 100 ms beträgt, kann das Protokoll Paketverluste erst nach 100 ms erkennen. Dieser Wert kann manuell geändert werden:
kcp->rx_minrto = 10 ;
Die Verwendung und Konfiguration des Protokolls ist sehr einfach. In den meisten Fällen können Sie es grundsätzlich verwenden, nachdem Sie den obigen Inhalt gelesen haben. Wenn Sie eine detailliertere Steuerung benötigen, z. B. eine Änderung der Speicherzuweisung von KCP, oder wenn Sie KCP-Verbindungen in großem Umfang (z. B. mehr als 3500) effizienter planen möchten oder eine bessere Integration mit TCP wünschen, können Sie dies tun weiterlesen:
Verwandte Lektüre: „Genshin Impact“ nutzt KCP auch, um Spielnachrichten zu beschleunigen
KCP wurde erfolgreich in mehreren Projekten mit Hunderten Millionen Benutzern eingesetzt und bietet ihnen ein reaktionsschnelleres und reibungsloseres Netzwerkerlebnis.
Gerne können Sie uns weitere Fälle mitteilen
Wenn das Netzwerk niemals hängen bleibt, verhält sich KCP/TCP ähnlich, aber das Netzwerk selbst ist unzuverlässig und Paketverlust und Jitter sind unvermeidlich (wozu sollten wir sonst verschiedene zuverlässige Protokolle benötigen)? Beim direkten Vergleich in einer nahezu idealen Umgebung wie dem Intranet sind alle nahezu gleich. Bei der Platzierung im öffentlichen Netzwerk, in einem 3G/4G-Netzwerk oder bei der Verwendung der Intranet-Paketverlustsimulation wird die Lücke jedoch offensichtlich. Im öffentlichen Netzwerk kommt es in Spitzenzeiten zu einem durchschnittlichen Paketverlust von fast 10 %, bei WLAN/3G/4G ist es sogar noch schlimmer, was zu Übertragungsverzögerungen führt.
Vielen Dank an Zhangyuan, den Autor von asio-kcp, für die horizontale Bewertung von KCP, enet und udt. Die Schlussfolgerungen lauten wie folgt:
Einzelheiten finden Sie unter: Horizontale Vergleichs- und Bewertungsdaten bieten weitere Orientierungshilfen für diejenigen, die bei der Auswahl zögern.
Die Massive-Multiplayer-Gameserver-Engine SpatialOS hat nach der Integration des KCP-Protokolls die gleiche Bewertung wie TCP/RakNet vorgenommen:
Wir haben die Reaktionszeit bei gleichzeitiger Beibehaltung von 50 Zeichen mit einer Bildwiederholfrequenz von 60 Hz auf der Serverseite verglichen. Bitte sehen Sie sich den ausführlichen Vergleichsbericht an:
In den letzten Jahren sind Online-Spiele und verschiedene soziale Netzwerke exponentiell gewachsen. Die Interaktivität und Komplexität nimmt schnell zu und sie alle müssen in sehr kurzer Zeit Daten liefern Für viele Benutzer wird die Übertragungstechnologie natürlich ein wichtiger Faktor sein, der die zukünftige Entwicklung einschränkt, und verschiedene bekannte Übertragungsprotokolle in der Open-Source-Welt, wie z. B. Raknet/Enet Wenn beispielsweise eine Veröffentlichung erfolgt, wird der gesamte Protokollstapel gemeinsam veröffentlicht. Dieses Formular ist nicht förderlich für die Diversifizierung. Es ist schwierig, „Sie teilweise zu verwenden“ zu wählen Eine Reihe von Protokollstapeln mag noch so gut sein, es ist jedoch sehr schwierig, verschiedene Anforderungen aus verschiedenen Blickwinkeln zu erfüllen.
Daher besteht die Methode von KCP darin, den Protokollstapel zu „zerlegen“, sodass jeder ihn entsprechend den Projektanforderungen flexibel anpassen und zusammenstellen kann. Sie können unten eine Ebene des Reed-Solomon-Löschcodes für FEC und eine darüber liegende Ebene für RC4/Salsa20 hinzufügen. Für die Stream-Verschlüsselung wird beim Handshake ein asymmetrischer Schlüsselaustausch entwickelt und auf der zugrunde liegenden UDP-Transportschicht ein dynamisches Routing-System aufgebaut, um mehrere Pfade gleichzeitig zu erkennen und den besten Pfad für die Übertragung auszuwählen. Diese verschiedenen „Protokolleinheiten“ können wie Bausteine nach Bedarf frei kombiniert werden, um „Einfachheit“ und „Abtrennbarkeit“ zu gewährleisten, sodass sie sich flexibel an sich ändernde Geschäftsanforderungen anpassen können. Wenn ein Modul nicht gut ist, ersetzen Sie es einfach.
Zukünftige Übertragungslösungen müssen je nach Nutzungsszenario umfassend angepasst werden. Daher stellen wir jedem eine „Protokolleinheit“ zur Verfügung, die frei kombiniert werden kann, um die Integration in den eigenen Protokollstapel zu erleichtern.
Weitere Informationen finden Sie in den Erfolgsgeschichten.
Autor: Lin Wei (skywind3000)
Willkommen, mir zu folgen auf: persönlichem Blog und Twitter.
In meiner langjährigen Entwicklungserfahrung habe ich immer gerne einige Engpassprobleme in Programmen studiert und gelöst. In meinen frühen Jahren habe ich mich für die Spieleentwicklung interessiert und das „Graphics Program“ von Michael Abrash gelesen Entwicklerhandbuch“ für Soft-Rendering. Ich spiele gerne mit Code, der die CPU auslasten und schneller laufen kann. Nach meinem Einstieg in die Arbeit verlagerte sich mein Interesse auf serverseitige und netzwerkbezogene Technologien.
Im Jahr 2007, nachdem ich mehrere traditionelle Spiele entwickelt hatte, begann ich, mich mit dem Synchronisationsproblem von Schnellspielspielen zu befassen. In dieser Zeit war ich einer der ersten Menschen in China, die sich mit Synchronisationsproblemen befassten Unabhängig davon, wie die Synchronisierung gelöst werden kann, müssen wir etwas in Bezug auf die Netzwerkübertragung tun. Nachdem ich das Spiel verlassen und zum Internet gewechselt war, stellte ich fest, dass in vielen Bereichen dieser Bedarf besteht, und begann, Zeit im Bereich der Netzwerkübertragung zu verbringen , versucht, einige konservative und zuverlässige Protokolle basierend auf UDP zu implementieren und den Code von BSD Lite 4.4 zu imitieren, um einige TCP-ähnliche Protokolle zu implementieren Ich fand es ziemlich interessant und implementierte dann einige Spielzeuge im Zusammenhang mit P2P und dynamischen Routing-Netzwerken. Das KCP-Protokoll wurde 2011 geboren. Es ist im Grunde eines von mehreren Spielzeugen, die in Bezug auf die Übertragung selbst hergestellt wurden.
Der Autor von Kcptun, xtaci, ist mein Studienkollege. Wir studieren beide als Hauptfach Kommunikation und lernen oft gemeinsam, wie wir die Übertragung optimieren können.
Willkommen bei Alipay, um den obigen QR-Code zu scannen und für dieses Projekt zu spenden. Spenden werden dazu verwendet, das KCP-Protokoll kontinuierlich zu optimieren und die Dokumentation zu verbessern.
Dank an: 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 , Hua Bin, Rutao, Hu Jian. . . (Es tut mir leid, dass ich die frühere Liste nicht aufgezeichnet habe.) Wir warten auf die Spenden und die Unterstützung unserer Klassenkameraden.
Seien Sie herzlich willkommen, aufmerksam zu sein
KCP-Kommunikationsgruppe: 364933586 (QQ-Gruppennummer), KCP-Integration, Abstimmung, Netzwerkübertragung und zugehörige technische Diskussionen
Gitter-Gruppe: https://gitter.im/skywind3000/KCP
Blog: http://www.skywind.me
Dieses Projekt existiert dank aller Menschen, die dazu beitragen.