KCPは高速で信頼性の高いプロトコルであり、平均遅延の10%〜20%の削減と最大遅延の30倍の削減と引き換えに、TCPと比較して帯域幅の40%〜<>%を浪費します。 純粋なアルゴリズムの実装は、基になるプロトコル(UDPなど)の送受信を担当せず、ユーザーは下位層パケットの送信方法を定義し、コールバックの形式でKCPに提供する必要があります。 クロックも外部に渡す必要があり、内部では単一のシステムコールはありません。
プロトコル全体には、ikcp.hとikcp.cの2つのソースファイルしかなく、ユーザー独自のプロトコルスタックに簡単に統合できます。 P<>PまたはUDPベースのプロトコルを実装していて、ARQの信頼できるプロトコル実装の完全なセットが不足している場合は、これら<>つのファイルを既存のプロジェクトにコピーし、<>行のコードを少し記述するだけで使用できます。
TCPはトラフィック(毎秒何キロバイトのデータを転送できるか)用に設計されており、帯域幅を最大限に活用することにこだわっています。 一方、KCPは、流量(10つのパケットが一方の端からもう一方の端に移動するのにかかる時間)に合わせて設計されており、帯域幅が20%〜30%無駄になるという犠牲を払って、TCPよりも40%〜<>%高速です。 TCPチャネルは、流量は遅いが毎秒の流量が多い大きな運河ですが、KCPは乱流のある小さな急流です。 KCPは通常モードと高速モードで利用可能であり、流量を増やす結果を達成するために次の戦略が使用されます。
TCPタイムアウトの計算はRTOx2であるため、パケットを8回連続で失うとRTOx2になり、非常に恐ろしいことであり、KCPは高速モードを開始した後のx1ではなくx5.1(実験では5.<>の値が比較的良好であることが証明されています)であり、伝送速度が向上します。
TCPパケット損失は、ドロップされたパケットからすべてのデータを再送信し、KCPは選択的再送信され、失われたパケットのみをファックスします。
送信者は、いくつかのパケット1、2、3、4、5を送信し、リモートエンドのACKを受信します:1、3、4、5、ACK3が受信されると、KCPは2が1回スキップされたことを認識し、ACK4を受信すると、2が2回スキップされたことを認識し、この時点で2号が失われたと見なすことができ、タイムアウトを待たずに、パケット番号2を直接再送信し、パケット損失時の伝送速度を大幅に向上させます。
帯域幅を最大限に活用するために、TCPはACKの送信を遅らせる(NODELAYは役に立たない)ため、タイムアウト計算では大きなRTT時間が計算され、パケット損失時の判断プロセスが長くなります。 KCP の ACK を遅延させるかどうかは調整できます。
ARQモデルの応答には、UNA(TCPなど、この番号より前に受信されたすべてのパケット)とACK(番号付きのパケットが受信された)の2種類があり、UNAのみを使用するとすべての再送信が発生し、ACKのみを使用するとコストが高すぎるため、前のプロトコルは2つのうちの1つであり、KCPプロトコルでは、個別のACKパッケージを除いて、すべてのパケットにUNA情報があります。
KCP の通常モードは、TCP のような公平バックオフ規則を使用します、つまり、送信ウィンドウのサイズは、送信キャッシュのサイズ、受信側の残りの受信キャッシュのサイズ、パケット損失、スロースタートの 4 つの要素によって決まります。 ただし、適時性の高い要件を持つ小さなデータを転送する場合は、構成の最後の2つのステップをスキップし、最初の2つのステップのみを使用して送信周波数を制御することを選択できます。 部分的な公平性と帯域幅使用率を犠牲にして、BTをオンにした状態でのスムーズな送信の効果と引き換えに。
vcpkg ライブラリマネージャーを使用して kcp をダウンロードしてインストールできます。
git clone https://github.com/Microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install ./vcpkg install kcp
vcpkg の kcp ライブラリは、マイクロソフトのチーム メンバーとコミュニティの共同作成者によって最新の状態に保たれています。 バージョンが古い場合は、問題を作成するか、vcpkg リポジトリに PR を提出してください。
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、サイズ) を使用してデータを受信します。
プロトコルのデフォルトモードは標準のARQであり、設定によってアクセラレーションスイッチをオンにする必要があります。
作業モード:
int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
最大ウィンドウ:
int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd);
この呼び出しにより、プロトコルの最大送信ウィンドウと最大受信ウィンドウ サイズが設定されます (既定値は 32)。 これはTCPのSND_BUFとRCV_BUFとして理解できるが、単位は異なるSND/RCV_BUF単位はバイトであり、この単位はパケットである。
最大伝送単位:
純粋なアルゴリズムプロトコルはMTUのプローブを担当せず、デフォルトのMTUは1400バイトであり、値はikcp_setmtuを使用して設定できます。 この値は、パケット統合およびフラグメンテーション時の最大伝送単位に影響します。
最小 RTO :
RTOを計算するのがTCPであろうとKCPであろうと、計算されたRTOが40msであっても、デフォルトのRTOは100msであるため、プロトコルは100ms、高速モードでは30ms後にパケット損失を検出できるため、手動で値を変更できます。
kcp->rx_minrto = 10;
プロトコルの使い方や設定は非常に簡単で、基本的には上記の内容を読んだ上で使えることがほとんどです。 KCPのメモリアロケータを変更するなど、さらにきめ細かい制御が必要な場合、KCPリンクをより効率的かつ大規模にスケジュールする必要がある場合(3500以上など)、またはTCPとの統合を改善する方法がある場合は、読み続けることができます。
KCPは、数億人のユーザーがいる複数のプロジェクトで正常に実行され、より応答性が高く、シルキーなWebエクスペリエンスを提供します。
より多くのケースを歓迎します
ネットワークがスタックしない場合、KCP / TCPは同様に動作しますが、ネットワーク自体は信頼できず、パケット損失とジッターを回避できません(そうでなければ、なぜさまざまな信頼できるプロトコルが必要なのですか)。 イントラネットのほぼ理想的な環境では、誰もが似ていますが、パブリックネットワークに配置するか、3G / 4Gネットワ ークの場合に配置するか、イントラネットパケット損失シミュレーションを使用すると、ギャップは明らかです。 パブリックネットワークでは、ピーク時の平均パケット損失が10%近くあり、WiFi / 3G / 4Gではさらに悪化し、送信がカードになります。
asio-kcpの著者であるZhangyuanのおかげで、KCPとenet、udtの水平レビューを行い、結論は次のとおりです。
具体见:横向比较 和 评测数据,为犹豫选择的人提供了更多指引。
大型多人游戏服务端引擎 SpatialOS 在集成 KCP 协议后做了同 TCP/RakNet 的评测:
对比了在服务端刷新率为 60 Hz 同时维护 50 个角色时的响应时间,详细对比报告见:
近年来,网络游戏和各类社交网络都在成几何倍数的增长,不管网络游戏还是各类互动社交网络,交互性和复杂度都在迅速提高,都需要在极短的时间内将数据同时投递给大量用户,因此传输技术自然变为未来制约发展的一个重要因素,而开源界里各种著名的传输协议,如 raknet/enet 之类,一发布都是整套协议栈一起发布,这种形式是不利于多样化的,我的项目只能选择用或者不用你,很难选择 “部分用你”,然而你一套协议栈设计的再好,是非常难以满足不同角度的各种需求的。
因此 KCP 的方式是把协议栈 “拆开”,让大家可以根据项目需求进行灵活的调整和组装,你可以下面加一层 reed solomon 的纠删码做 FEC,上面加一层类 RC4/Salsa20 做流加密,握手处再设计一套非对称密钥交换,底层 UDP 传输层再做一套动态路由系统,同时探测多条路径,选最好路径进行传输。这些不同的 “协议单元” 可以像搭建积木一般根据需要自由组合,保证 “简单性” 和 “可拆分性”,这样才能灵活适配多变的业务需求,哪个模块不好,换了就是。
未来传输方面的解决方案必然是根据使用场景深度定制的,因此给大家一个可以自由组合的 “协议单元” ,方便大家集成在自己的协议栈中。
For more information, please see the Success Stories.
作者:林伟 (skywind3000)
我在多年的开发经历中,一直都喜欢研究解决程序中的一些瓶颈问题,早年喜欢游戏开发,照着《VGA编程》来做游戏图形,读 Michael Abrash 的《图形程序开发人员指南》做软渲染器,爱好摆弄一些能够榨干 CPU 能够运行更快的代码,参加工作后,兴趣转移到服务端和网络相关的技术。
2007年、いくつかの伝統的なゲームをやった後、高速アクションゲームの同期問題を研究し始め、その間に多くの記事を書き、中国で最も早く同期問題を研究したと考えられていましたが、同期を解決する方法に関係なく、ネットワーク伝送に突破口を開き、その後、ゲームを離れてインターネットに切り替え、多くの地域がこの需要を持っていることにも気づき、ネットワーク伝送の分野で時間を費やし始め、BSD Lite 4.4をモデルにしたUDPに基づく保守的で信頼性の高いプロトコルを実装しようとしました。 このコードは、私が興味深いと思うTCPのようなプロトコルをいくつか実装し、次にいくつかのP2Pおよび動的ルーティングネットワーク関連のおもちゃを実装します。 KCPプロトコルは2011年に誕生し、基本的に独自の送信に関して作られたいくつかのおもちゃの<>つです。
Kcptunの作者であるxtaciは私の大学の同級生であり、私たちはコミュニケーションを研究し、送信を最適化する方法についてしばしば一緒に働きました。
Alipayを使用して上記のQRコードをスキャンしてプロジェクトに寄付することを歓迎します。 寄付金は、KCPプロトコルを継続的に最適化し、ドキュメントを改善するために使用されます。
ありがとう:ミンミン、シンザイ、ジン、ファン、フージャオ、ビンクアン、シャオダン、ユーチェン、フー、シェンダーン、シューウェイ、ワンチュアン、チャオガンチャン、フージフェン、ワンシンチャオ、ホーシンチャオ、リウヤン、ホウシアンフイ、ウーペイイー、フアビン、ルータオ、フージェン... (以前のリストを記録せずに申し訳ありません)そして他の学生の寄付と支援。
フォローへようこそ
KCP通信グループ:364933586(QQグループ番号)、KCP統合、チューニング、ネットワーク伝送および関連する技術的議論
ギッターグループ:https://gitter.im/skywind3000/KCP