一、背景
常见的网络模型,主要是七层模型和五层模型。七层模型可以记为物数网传会应表,五层模型就是把会应表合并为了应用层。tcp/udp/kcp都是传输层的协议。
这里我们重点关注TCP和UDP。协议特点的差异如下表所示:
选项 | UDP | TCP |
是否连接 | 否 | 是 |
是否可靠 | 否 | 是 |
连接对象个数 | 一对一,一对多,多对一和多对多 | 只支持一对一 |
传输方式 | 面向报文 | 面向字节流 |
首部开销 | 小,8字节 | 大,20-60字节 |
适用场景 | 电话、视频会议、直播、游戏等 | 文件传输 |
TCP和UDP的格式对比
TCP主要通过以下方式来保证数据传输的可靠性:
-
序列号和确认应答:TCP使用序列号对发送的数据进行编号,接收方在收到数据后会发送确认应答,通知发送方已成功接收。如果发送方在合理的时间内没有收到确认,就会重新发送数据。重传机制分为GBN和SR,前者采用累计确认,某个数据包没有收到确认号,会重发该数据包和之后所有的数据包,后者每个数据包采用单独的计时器,超时之后只会重传未收到确认号的数据包。
-
数据校验和重传:TCP在数据包中使用校验和字段,接收方会验证数据的完整性。如果数据包损坏,接收方会丢弃该数据包并要求发送方重新发送。发送方也会定期重发未收到确认的数据包,确保数据的可靠传输。
-
流量控制和拥塞控制:TCP会根据网络状况动态调整发送数据的速率,以避免网络拥塞和数据丢失。它使用滑动窗口和拥塞控制算法来实现这一点。当发送方收到接 收窗口的大小为0时,发送方就会停止发送数据,防止出现大量丢包情况的发生。当发送方收到接受窗口 win = 0 时,这时发送方停止发送报文,并且同时开启一个定时器,每隔一段 时间就发个测试报文去询问接收方,打听是否可以继续发送数据了,如果可以,接收方就告诉他此时 接受窗口的大小;如果接受窗口大小还是为0,则发送方再次刷新启动定时器。
-
连接管理:TCP使用三次握手建立连接和四次挥手关闭连接,确保通信双方的状态同步,从而避免数据丢失或重复传输。
二、活在应用层的KCP传输协议
UDP就没有可靠性的保证了,直接听天由命。为什么收不到数据,还不是你不够努力?
能不能给UDP加上一些TCP的特性,来实现相对可靠的快速数据传输呢?经过改进后的UDP其实就是KCP,也就是说KCP是一个基于UDP改进的传输协议,但是要注意KCP是一个用户态协议,它不直接操作网络硬件,需要开发者在应用层实现UDP的收发,并通过回调等方式将数据传递给KCP。KCP提供了更多的灵活性和定制性,但也意味着实现复杂度相对较高。
KCP在UDP上应用了TCP的部分机制并且更改了数值!例如:
(1)TCP超时计算翻倍,KCP超时计算只有1.5倍
(2)丢包之后TCP从丢包的数据开始全部重传,KCP选择性重传
(3)快速重传,在某个数据包发送后收到了n个数据包的确认号,不用怀疑这个数据包肯定丢了,直接重传!
(4)KCP协议中,除去单独的 ACK包外,所有包都有UNA(此编号前所有包已收到)信息。这里说明一下,TCP和KCP都是面向连接的全双工协议,发送端和接收端的数据传输是相互的,接收端出了ack数据包外还可能发送其它的数据包,在其他的数据包中也加入UNA信息就避免了增加太多的网络开销,遥遥领先!
(5)KCP作为应用层实现的传输协议继续领先!甚至可以动态调整延迟ACK和非延迟ACK
(6)动态调整发送窗口的大小,由发送缓存大小,接收端剩余接收缓存大小,丢包退让和慢启动
KCP的协议头如下所示:
上图的数字代表数组下标。
0-3:conv-连接号。UDP是无连接的,conv用于表示来自于哪个 客户端。对连接的一种替代
4:cmd-命令字。如,IKCP_CMD_ACK确认命令
5:frg-分片。用户数据可能会被分成多个KCP包
6-7:wnd-接收窗口大小
8-11:时间序列
12-15:序列号
16-19:下一个可接收的序列号。其实就是确认号,例如收到 sn=10的包,una为11。
20-23:数据长度
data:用户数据,这是本次发送的数据长度
至于怎么使用KCP传输协议,日后再说。
这是一条吃饭博客,由挨踢零声赞助