영어로 읽어보세요
KCP는 TCP보다 10~20% 더 많은 대역폭을 사용하여 평균 지연을 30~40%, 최대 지연을 3배 줄일 수 있는 빠르고 안정적인 프로토콜입니다. 순수 알고리즘 구현은 기본 프로토콜(예: UDP)의 전송 및 수신을 담당하지 않습니다. 사용자는 하위 계층 데이터 패킷의 전송 방법을 정의하고 이를 콜백 형식으로 KCP에 제공해야 합니다. 시계도 외부에서 전달되어야 하며 내부적으로 시스템 호출이 발생하지 않습니다.
전체 프로토콜에는 ikcp.h와 ikcp.c라는 두 개의 소스 파일만 있으며 이는 사용자 자신의 프로토콜 스택에 쉽게 통합될 수 있습니다. P2P 또는 UDP 기반 프로토콜을 구현했지만 완전하고 안정적인 ARQ 프로토콜 구현이 부족한 경우 이 두 파일을 기존 프로젝트에 복사하고 몇 줄의 코드를 작성하면 사용할 수 있습니다.
TCP는 트래픽(초당 몇 KB의 데이터를 전송할 수 있는지)을 위해 설계되었으며 대역폭을 최대한 활용하는 데 중점을 둡니다. KCP는 흐름 속도(단일 데이터 패킷이 한 끝에서 다른 끝으로 전송되는 데 걸리는 시간)를 위해 설계되었습니다. 이는 대역폭 낭비의 10%-20%를 TCP보다 30%-40% 빠른 전송 속도로 교환합니다. . TCP 채널은 유속은 느리지만 초당 유속이 큰 큰 운하인 반면, KCP 채널은 유속이 빠르고 작은 급류입니다. KCP에는 일반 모드와 고속 모드의 두 가지 유형이 있습니다. 유속 증가 결과는 다음 전략을 통해 달성됩니다.
TCP 타임아웃 계산은 RTOx2입니다. 연속해서 3개의 패킷을 잃으면 RTOx8이 되는데, 이는 매우 무섭습니다. 그러나 KCP가 고속 모드를 시작한 후에는 x2가 아니라 x1.5만 됩니다(실험을 통해 입증됨). 1.5의 값이 비교적 양호함), 전송 속도가 향상됩니다.
TCP가 패킷을 손실하면 손실된 패킷부터 시작하여 모든 데이터를 재전송합니다. KCP는 선택적으로 재전송하고 실제로 손실된 데이터 패킷만 재전송합니다.
발신자는 여러 개의 패킷 1, 2, 3, 4, 5를 보낸 후 원격 끝에서 1, 3, 4, 5의 ACK를 받았습니다. ACK3을 수신할 때 KCP는 2가 한 번 건너뛴 것을 알고 ACK4를 수신했을 때 이때, 2번 패킷이 손실된 것으로 간주할 수 있으며, 타임아웃을 기다릴 필요 없이 2번 패킷을 바로 재전송할 수 있어 크게 개선된다. 패킷이 손실되었을 때의 전송 속도.
대역폭을 최대한 활용하기 위해 TCP는 ACK 전송을 지연시킵니다(NODELAY는 쓸모가 없습니다). 이러한 방식으로 타임아웃 계산은 더 큰 RTT 시간을 계산하므로 패킷 손실이 발생할 때 판단 프로세스가 길어집니다. KCP의 ACK가 지연되어 전송되는지 여부를 조정할 수 있습니다.
ARQ 모델 응답에는 UNA(TCP와 같이 이 번호 이전의 모든 패킷이 수신됨)와 ACK(이 번호가 있는 패킷이 수신됨)의 두 가지 유형이 있습니다. UNA만 사용하면 모든 재전송이 발생하고 ACK만 사용하면 재전송이 발생합니다. 손실 비용이 너무 높음. 과거에는 둘 중 하나만 선택하면 되는 프로토콜이었지만, KCP 프로토콜에서는 개별 ACK 패킷을 제외한 모든 패킷에 UNA 정보가 포함됩니다.
KCP 일반 모드는 TCP와 동일한 공정한 양보 규칙을 사용합니다. 즉, 송신 창 크기는 송신 버퍼 크기, 수신 측의 나머지 수신 버퍼 크기, 패킷 손실 양보 및 느린 시작의 네 가지 요소에 의해 결정됩니다. 그러나 적시성이 요구되는 소규모 데이터를 전송할 경우 구성의 마지막 두 단계를 건너뛰고 처음 두 항목만 사용하여 전송 빈도를 제어할 수 있습니다. 부분적인 공평성과 대역폭 활용을 희생하여 BT를 켠 상태에서도 원활한 전송 효과를 얻을 수 있습니다.
vcpkg 라이브러리 관리자를 사용하여 kcp를 다운로드하고 설치할 수 있습니다.
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install kcp
vcpkg의 kcp 라이브러리는 Microsoft 팀 구성원과 커뮤니티 참가자에 의해 최신 상태로 유지됩니다. 버전이 오래된 경우 문제를 생성하거나 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, 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입니다. 이는 TCP의 SND_BUF 및 RCV_BUF로 이해될 수 있지만 단위는 다릅니다. SND/RCV_BUF 단위는 바이트이며 이 단위는 입니다. 패킷.
최대 전송 단위:
순수 알고리즘 프로토콜은 MTU 감지를 담당하지 않습니다. 기본 mtu는 ikcp_setmtu를 사용하여 이 값을 설정할 수 있습니다. 이 값은 데이터 패킷을 결합하고 조각화할 때 최대 전송 단위에 영향을 미칩니다.
최소 RTO:
TCP이든 KCP이든 RTO 계산 시 최소 RTO 제한이 있습니다. 계산된 RTO가 40ms라도 기본 RTO는 100ms이므로 프로토콜은 100ms 후에만 패킷 손실을 감지할 수 있습니다. 이 값은 수동으로 변경할 수 있습니다.
kcp->rx_minrto = 10 ;
프로토콜의 사용 및 구성은 대부분의 경우 위의 내용을 읽어보신 후 기본적으로 사용하실 수 있습니다. KCP의 메모리 할당자 변경과 같이 더욱 세부적인 제어가 필요하거나 대규모(예: 3500개 이상) KCP 연결을 보다 효율적으로 예약해야 하거나 TCP와 더 잘 통합하는 방법이 필요한 경우 다음을 수행할 수 있습니다. 계속 읽으세요:
관련 읽기: "Genshin Impact"도 KCP를 사용하여 게임 뉴스 속도를 높이고 있습니다.
KCP는 수억 명의 사용자가 있는 여러 프로젝트에서 성공적으로 실행되어 보다 반응성이 뛰어나고 부드러운 네트워크 경험을 제공했습니다.
더 많은 사례를 알려주신 것을 환영합니다.
네트워크가 절대로 중단되지 않으면 KCP/TCP는 유사하게 작동하지만 네트워크 자체는 신뢰할 수 없으며 패킷 손실과 지터는 피할 수 없습니다(그렇지 않으면 신뢰할 수 있는 다양한 프로토콜이 왜 필요합니까)? 인트라넷과 같은 거의 이상적인 환경에서 직접 비교하면 모든 사람이 거의 동일하지만 공용 네트워크에 배치하거나 3G/4G 네트워크에 배치하거나 인트라넷 패킷 손실 시뮬레이션을 사용하면 차이가 분명해집니다. 공용 네트워크는 피크 기간 동안 평균 패킷 손실이 10%에 가깝고, WiFi/3g/4g에서는 더욱 악화되어 전송 지연이 발생합니다.
KCP, enet, udt에 대한 수평적 평가를 해준 asio-kcp의 저자 zhangyuan에게 감사드립니다.
자세한 내용은 수평적 비교 및 평가 데이터를 참조하세요. 선택을 망설이는 사람들에게 더 많은 지침을 제공합니다.
대규모 멀티플레이어 게임 서버 엔진 SpatialOS는 KCP 프로토콜을 통합한 후 TCP/RakNet과 동일한 평가를 수행했습니다.
서버 측에서 새로고침 빈도를 60Hz로 동시에 50자를 유지할 때의 응답 시간을 비교했습니다. 자세한 비교 보고서를 참조하세요.
최근 몇 년 동안 온라인 게임과 다양한 소셜 네트워크가 기하급수적으로 성장하면서 상호작용성과 복잡성이 급격히 증가하고 있으며, 모두 매우 짧은 시간에 동시에 많은 양의 데이터를 전달해야 합니다. 사용자의 전송 기술은 자연스럽게 향후 개발을 제한하는 중요한 요소가 될 것이며, raknet/enet과 같은 오픈 소스 세계에서 잘 알려진 다양한 전송 프로토콜이 있습니다. 예를 들어, 릴리스가 이루어지면 전체 프로토콜 스택이 함께 릴리스됩니다. 이 형식은 다양화에 도움이 되지 않습니다. 내 프로젝트는 "부분적으로 사용"을 선택할 수 있지만 디자인은 어렵습니다. 아무리 좋은 프로토콜 스택이라도 다양한 각도에서 다양한 요구를 충족시키는 것은 매우 어렵습니다.
따라서 KCP의 방법은 모든 사람이 프로젝트 요구에 따라 유연하게 조정하고 조립할 수 있도록 프로토콜 스택을 "분해"하는 것입니다. FEC를 위해 아래에 리드 솔로몬의 삭제 코드 레이어를 추가하고 RC4/Salsa20을 위해 그 위에 레이어를 추가할 수 있습니다. 스트림 암호화의 경우 핸드셰이크 시 비대칭 키 교환이 설계되고 기본 UDP 전송 계층에 동적 라우팅 시스템이 구축되어 동시에 여러 경로를 감지하고 전송에 가장 적합한 경로를 선택합니다. 이러한 다양한 "프로토콜 유닛"은 빌딩 블록처럼 필요에 따라 자유롭게 결합하여 "단순성"과 "분리성"을 보장하므로 변화하는 비즈니스 요구에 유연하게 적응할 수 있습니다. 모듈이 좋지 않으면 교체하면 됩니다.
미래의 전송 솔루션은 사용 시나리오에 따라 심층적으로 맞춤화되어야 하므로 모든 사람에게 자유롭게 결합하여 자체 프로토콜 스택에 쉽게 통합할 수 있는 "프로토콜 장치"를 제공합니다.
자세한 내용은 성공 사례를 참조하세요.
저자: 린 웨이(skywind3000)
개인 블로그와 트위터에서 저를 팔로우하신 것을 환영합니다.
수년간의 개발 경험을 통해 저는 항상 프로그램의 병목 현상 문제를 연구하고 해결하는 것을 좋아했습니다. 초창기에는 게임 개발을 좋아했으며 게임 그래픽을 만들기 위해 "VGA 프로그래밍"을 좋아했고 Michael Abrash의 "그래픽 프로그램"도 읽었습니다. 개발자 가이드"를 참조하여 소프트 렌더링을 수행합니다. 저는 CPU를 쥐어 짜내고 더 빠르게 실행할 수 있는 코드를 가지고 노는 것을 좋아합니다. 이 작업에 합류한 후 제 관심은 서버 측 및 네트워크 관련 기술로 옮겨졌습니다.
2007년에 여러 가지 전통 게임을 만든 후 빠른 액션 게임의 동기화 문제를 연구하기 시작했습니다. 이 기간 동안 나는 중국에서 동기화 문제를 연구한 최초의 사람 중 한 명이었습니다. 동기화를 어떻게 해결하든 네트워크 전송 측면에서 뭔가를 해야 합니다. 게임을 종료하고 인터넷으로 전환한 후 많은 분야에서 이러한 필요성이 있다는 사실을 알게 되었기 때문에 네트워크 전송 분야에 시간을 보내기 시작했습니다. UDP를 기반으로 보수적이고 신뢰할 수 있는 프로토콜을 구현하려고 시도하고 BSD Lite 4.4의 코드를 모방하여 TCP와 유사한 일부를 구현했습니다. 프로토콜에 대해 꽤 흥미로웠고 P2P 및 동적 라우팅 네트워크와 관련된 몇 가지 장난감을 구현했습니다. KCP 프로토콜은 2011년에 탄생했습니다. 기본적으로 전송 측면에서 자체적으로 만든 여러 장난감 중 하나입니다.
Kcptun의 저자인 xtaci는 저의 대학 동창입니다. 우리 둘 다 커뮤니케이션을 전공하고 있으며 전송 최적화 방법을 함께 연구하는 경우가 많습니다.
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 , Hua Bin, Rutao, Hu Jian. . . (앞서 목록을 기록하지 못해 죄송합니다.) 학우분들의 기부와 응원을 기다립니다.
관심을 환영합니다
KCP 통신 그룹: 364933586(QQ 그룹 번호), KCP 통합, 튜닝, 네트워크 전송 및 관련 기술 논의
기터 그룹: https://gitter.im/skywind3000/KCP
블로그: http://www.skywind.me
이 프로젝트는 기여하는 모든 사람들 덕분에 존재합니다.