KCP协议

作者: Frank_Kivi | 来源:发表于2019-05-29 14:23 被阅读0次

1 简介

KCP是一个快速可靠协议,能以比TCP浪费10%-20%的带宽的代价,换取平均延迟降低30%-40%,且最大延迟降低三部的传输效果。纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者自己定义下层数据包的发送方式,以callback的方式提供给KCP。连时钟都需要外部传递进来,内部不会有任何一次系统调用。

2 技术特性

TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的是充分利用带宽。而KCP是为流速设计的(单个数据包从一端发送到另一端需要多少时间),以10%-20%带宽浪费的代价换取了比TCP快30%-40%的传输速度。TCP信道是一条流程很慢,但每秒流量很大的大运河,而KCP是水流湍急的小激流。KCP有正常模式和快速模式两种,通过以下策略达到提高流速的结果:

RTO翻倍 VS 不翻倍:

TCP超时计算是RTOx2,这样连续丢三次包就变成RTOx8了,十分恐怖,而KCP启动快速度模式后不是x2,只是x1.5(实验证明1.5这个值相对比较好),提高了传输速度。

选择性重传 VS 全部重传:

TCP丢包时会全部重传从丢的那个包开始以后的数据,KCP是选择性重传,只重传真正丢失的数据包。

快速重传:

发送端发送了1,2,3,4,5几个包,然后收到远端的ACK:1,3,4,5,当收到ACK3时,KCP知道2被跳过1次,收到ACK4时,知道2被跳过了2次,此时可以认为2号丢失,不用等超时,直接重传2号包,大大改善了丢包时的传输速度。

延迟ACK VS 非延迟ACK:

TCP为了充分利用带宽,延迟发送ACK(NODELAY都没用),这样超时计算会算出比较大RTT时间,延长了丢包时的判断过程。KCP的ACK是否延迟发送可以调节。

UNA VS ACK+UNA:

ARQ模型响应有两种,UNA(此编号前所有包已收到,如TCP)和ACK(该编号包已收到),光用UNA将导致全部重传,光用ACK则丢失成本太高,以往协议都是二选其一,而KCP协议中,除去单独的ACK包外,所有包都有UNA信息。

非退让流控:

KCP正常模式同TCP一样使用公平退让法则,即发送窗口大小由:发送缓存大小、接收端剩余接收缓存大小、丢包退让及慢启动这四要素决定。但传递及时性要求很高的小数据时,可选择通过配置跳过后两步,仅用前两项来控制发送频率。以牺牲部分公平性及带宽利用率之代价,换取了开着BT都能流畅传输的效果。

3 协议定义

3.1 KCP协议
type segment struct {
conv uint32 
// 发送端与接收端通信时的匹配数字,发送端发送的数据包中此值与接收端的conv值匹配一致时,接收端才会接受此包

cmd uint8 
// 改数据包的协议号,协议号有以下枚举:
// IKCP_CMD_PUSH = 81 // cmd: push data,数据包
// IKCP_CMD_ACK = 82 // cmd: ack,确认包,告诉对方收到数据包
// IKCP_CMD_WASK = 83 // cmd: window probe (ask),询问远端滑动窗口的大小
// IKCP_CMD_WINS = 84 // cmd: window size (tell),告知远端滑动窗口的大小

frg uint8
// 分帧号,由于udp传输有数据包大小的限制,因此,应用层一个数据包可能被分为多个udp包

制自己接下来发送数据的大小wnd uint16
// 滑动窗口的大小
// 当Segment做为发送数据时,此wnd为本机滑动窗口大小,用于告诉远端自己窗口剩余多少
// 当Segment做为接收到数据时,此wnd为远端滑动窗口大小,本机知道了远端窗口剩余多少后,可以控

ts uint32
// timestamp , 当前Segment发送时的时间戳

sn uint32
// Sequence Number,Segment数据包的编号

una uint32
// una即unacknowledged,未确认数据包的编号,表示此编号前的所有包都已收到了。

rto uint32
// rto即Retransmission TimeOut,即超时重传时间,在发送出去时根据之前的网络情况进行设置

xmit uint32
// 基本类似于Segment发送的次数,每发送一次会自加一。用于统计该Segment被重传了几次,用于参考,进行调节

resendts uint32
// 即resend timestamp , 指定重发的时间戳,当当前时间超过这个时间时,则再重发一次这个包。

fastack uint32
// 用于以数据驱动的快速重传机制;

// len uint32 c++版本有数据包的数据长度,go版本无此字段

data []byte}
// 协议数据的具体内容
3.2 enet协议对比
typedef struct _ENetProtocolHeader{
        enet_uint16 peerID;
        enet_uint16 sentTime;
} ENET_PACKED ENetProtocolHeader;

typedef struct _ENetProtocolCommandHeader{
        enet_uint8 command;enet_uint8 channelID;
        enet_uint16 reliableSequenceNumber;
} ENET_PACKED ENetProtocolCommandHeader;

4 流程图

4.1发送流程
4.2接收流程

相关文章

  • 纯go生态的rpcx

    安装rpcx tags 对应: quic: 支持 quic 协议 kcp: 支持 kcp 协议 zookeeper...

  • iOS基础通讯UDP/KCP协议的使用

    我的demo地址:https://github.com/caobo56/KCPDemo 什么是KCP? kcp协议...

  • KCP协议

    1 简介 KCP是一个快速可靠协议,能以比TCP浪费10%-20%的带宽的代价,换取平均延迟降低30%-40%,且...

  • 在网络中狂奔:KCP协议

    在网络中狂奔:KCP协议 一、概述 TCP保证数据准确交付,UDP保证数据快速到达,KCP则是两种协议的一个折中。...

  • KCP协议简介

    如图在安装好达梦数据库开始初始化数据库时候出现了错误 出现这个问题就是license过期,就是dm.key文件过期...

  • Openwrt华硕固件Kcptun配置使用教程

    简介 Kcptun 是一个非常简单和快速的,基于 KCP 协议的 UDP 隧道,它可以将 TCP 流转换为 KCP...

  • kcp介绍

    KCP介绍 1 简介 KCP是一个快速可靠协议,能以比 TCP浪费10%-20%的带宽的代价,换取平均延迟降低 3...

  • Kcptun服务端一键安装脚本

    简介 Kcptun是一个异常简单和快速的,基于KCP协议的UDP地道,它可以将TCP流替换为KCP+UDP流。而K...

  • Java中使用KCP协议

    传统游戏项目一般使用TCP协议进行通信,得益于它的稳定和可靠,不过在网络不稳定的情况下,会出现丢包严重。不过近期有...

  • KCP协议:从TCP到UDP家族QUIC/KCP/ENET

    行文前先安利下《再深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP[https://www.zhou...

网友评论

    本文标题:KCP协议

    本文链接:https://www.haomeiwen.com/subject/hametctx.html