java kcp_KCP 介绍转载

KCP是一种快速可靠的协议,旨在以牺牲10%-20%带宽为代价,换取30%-40%的传输速度提升。它不负责底层协议如UDP的收发,而是专注于算法实现。KCP的特点包括:不翻倍的RTO、选择性重传、快速重传、非延迟ACK等,提供了更优的延迟和流速体验。此外,KCP协议结构和与ENet协议的对比也进行了说明。
摘要由CSDN通过智能技术生成

KCP介绍

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值匹配一致时,接收端才会接受此包

conv uint32

// 改数据包的协议号,协议号有以下枚举:

// 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),告知远端滑动窗口的大小

cmd uint8

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

frg uint8

// 滑动窗口的大小

// 当Segment做为发送数据时,此wnd为本机滑动窗口大小,用于告诉远端自己窗口剩余多少

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

wnd uint16

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

ts uint32

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

sn uint32

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

una uint32

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

rto uint32

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

xmit uint32

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

resendts uint32

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

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 发送流程

format,png

4.2 接收流程

format,png

Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持Java的任何平台上无需重新编译即可运行,这得益于其独特的跨平台性,通过Java虚拟机(JVM)实现不同操作系统上的兼容。 Java的特点包括: 面向对象:Java全面支持面向对象的特性,如封装、继承和多态,使得代码更易于维护和扩展。 安全:Java提供了丰富的安全特性,如禁止指针运算、自动内存管理和异常处理机制,以减少程序错误和恶意攻击的可能性。 可移植性:Java字节码可以在所有安装了JVM的设备上执行,从服务器到嵌入式系统,再到移动设备和桌面应用。 健壮性与高性能:Java通过垃圾回收机制确保内存的有效管理,同时也能通过JIT编译器优化来提升运行时性能。 标准库丰富:Java拥有庞大的类库,如Java SE(Java Standard Edition)包含基础API,用于开发通用应用程序;Java EE(Java Enterprise Edition)提供企业级服务,如Web服务、EJB等;而Java ME(Java Micro Edition)则针对小型设备和嵌入式系统。 社区活跃:Java有着全球范围内庞大的开发者社区和开源项目,持续推动技术进步和创新。 多线程支持:Java内建对多线程编程的支持,使并发编程变得更加简单直接。 动态性:Java可以通过反射、注解等机制实现在运行时动态加载类和修改行为,增加了程序的灵活性。 综上所述,Java凭借其强大的特性和广泛的适用范围,在企业级应用、互联网服务、移动开发等领域均扮演着举足轻重的角色,是现代软件开发不可或缺的重要工具之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值