UDP可靠性传输协议kcp

简介: UDP可靠性传输协议kcp

前言


本文先介绍TCP中实现可靠传输的方式, 引出KCP是如何在应用层实现UDP可靠性传输


 本专栏知识点是通过零声教育的线上课学习,进行梳理总结写下文章,对c/c++linux课程感兴趣的读者,可以点击链接 C/C++后台高级服务器课程介绍 详细查看课程的服务。


一、如何做到可靠性传输?


1.ACK机制


2.重传机制


3.序号机制


4.重排机制


5.窗口机制 流量控制 带宽有限


ARQ协议

ARQ协议: 即自动重传请求,是传输层的错误纠正协议之一,它通过使用确认和超时两个机制,保证可靠信息传输


主要有3种模式


1. 即停等待:


2. 回退N帧:  


对于接收方来说,若一个序号为 n 的分组被正确接收,并且按序,则接收方会为该分组返回一个ACK 给发送方,并将该分组中的数据交付给上层。在其他情况下,接收方都会丢弃分组。若分组n 已接收并交付,那么所有序号比 n小的分组也已完成了交付( 永远记住 ACK 是表示这之前的包都已经全部收到 )。如果序号为N的分组丢失,那么序号为N 以及 N 之后的分组都将被重传

3. 选择性重传:


RTT和RTO

RTO: 重传超时时间, RTO > RTT 时重传


RTT: 往返时延, 计算方式大概是 比如这个 SERVER A 时候发送包 A ,包A的头部携带时间戳, SERVER B 回传包A时会在头部带包A的时间戳(让SERVER A知道这个包是自己在什么时候发的, 从发包到现在接收到回传经过了多少时间  RTT = 当前时间戳 - 发包时间戳),


流量控制

为什么需要流量控制


双方在通信的时候, 发送方的速率与接收方的速率不一定相等, 如果发送方的发送速率太快, 接收方处理不过来, 此时接收方只能把处理不过来的数据存在缓存区里 (失序的数据包也会被存放在缓存区里)接收缓存。


如果缓存区满了发送方还在发送数据, 接收方只能把收到的数据包丢弃(大量的丢包会极大浪费网络资源),因此,需要控制发送方的发送速率, 让接收方与发送方处于一种平衡。


流量控制-如何控制


接收方每次收到数据包,可以在发送确定报文(ACK)的时候,在报文头部通过window Size 告诉发送方自己的缓冲区还剩余多少空闲区(接收窗口大小)


发送方收到后, 便会调整自己的发送速率(发送窗口大小),当发送方收到接收窗口的大小为0时, 发送方就会停止发送数据, 防止丢包



对端接收窗口忙了停止发送后, 发送方何时再发送数据


接收方主动通知:  当接收方处理好数据,接受窗口 win > 0 时,接收方发个通知报文去通知发送方,告诉他可以继续发送数据了。当发送方收到窗口大于0的报文时,就继续发送数据


窗口探测: 当发送方收到接受窗口 win = 0 时,这时发送方停止发送报文,并且同时开启一个定时器,每隔一段时间就发个测试报文去询问接收方,打听是否可以继续发送数据了,如果可以,接收方就告诉他此时接受窗口的大小;如果接受窗口大小还是为0,则发送方再次刷新启动定时器


通信的双方都拥有两个滑动窗口,一个用于接受数据,称之为接收窗口;一个用于发送数据,称之为拥塞窗口(即发送窗口)。指出接受窗口大小的通知我们称之为 窗口通告


拥塞控制

流量控制只关注发送方跟接受方自身的状况(接受方内核readbuff 大小),而没考虑到整个网络的通信状况(包体的往返时延 RTT),于是需要拥塞处理,让发送方与接收方出于一个更好的速率平衡。


拥塞处理主要涉及到下面这几个算法


慢启动(Slow Start):  每个TCP 连接都有一个拥塞(发送)窗口的限制,最初这个值很小, 随着时间的推移,每次发送的数据量如果在不丢包的情况下慢慢递增(逐渐测试放大发送包体的数据量),这种机制就是 慢启动

       计算方式:


       cwnd 初始值较小时,每收到一个 ACK,cwnd + 1,每经过一个 RTT,cwnd 变为之前的两倍


拥塞避免(Congestion Avoidance): 当拥塞窗口通过慢启动机制到达一个阀值时,拥塞窗口进入拥塞避免阶段(防止发送窗口无限扩张), 此时每一个 RTT, 拥塞窗口增加一个 MSS大小(1),直到检测到拥塞为止。

快速重传(Fast Retransmit):  当接受端收到一个不按序到达的数据时, 立即回传一个重复的ACK (比如此时 发送端 应该发送1003到接受端, 但是却发了一个1004, 接受端立马回了一个1004的ACK给发送端, 那么当发送端收到 3个或以上重复的ACK, 就意识到之前发的包(1003)可能丢了, 于是就可以马上进行重传 不用等超时重传)

快速恢复(Fast Recovery): 当收到三次重复 ACK 时,进入快速恢复阶段。解释为网络轻度拥塞。拥塞阀值降低到 发送窗口的一半,拥塞窗口 设置成 拥塞阀值 并且线性增加(每次加 1)

为了实现上面的算法,TCP 的每条连接都有两个核心状态值:


拥塞窗口(Congestion Window,cwnd): 拥塞窗口是发送端的限制, 是发送端还未收到对端ACK之前还能发送的数据。 假设此时已知对端的接受窗口大小是4KB,这时发给了对端 2KB,在未收到对端的ACK确认包时,这时自己还能发送给对方的数据最大应该是 4K-2K= 2KB(实际应该小于2KB, 慢启动的机制 让 拥塞窗口 逐渐变大)。

发送窗口大小 = 「接收端接收窗口大小(rwnd)」 与 「发送端自己拥塞窗口大小(cwnd)」 两者的最小值

慢启动阈值(Slow Start Threshold,ssthresh): 用于控制慢启动拥塞窗口的增长, 当拥塞窗口小于阀值时按指数级增长(慢启动)。 当拥塞窗口大于阀值时,触发拥塞避免,让拥塞窗口按线性增长

     

二、可靠性UDP-KCP


特性: 面向报文


recvform()读数据时需要把数据一次读完,否则会丢失


mtu: 建议发送1400字节


如果要同时监听多个端口, 可以考虑使用epoll方式管理(send recv)


如果只有单个端口,采用 recvfrom



1.UDP网络编程

UDP 编程 C++ 代码如下(示例):


2.KCP

       UDP 面相报文发送消息,简单说协议本身只管发而不管对端收没收到消息。那要如何实现UDP的可靠性传输,那就是把 TCP 的可靠机制移植过来在应用层中实现。目前成熟的可靠性传输算法有KCP, QUIC等。


重传时间(RTO)

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


以 RTO=100ms 为例:重传四次的情况下在TCP中的重传时间间隔分别是200, 400, 800, 1600而在KCP中分别是 200,300,  450,  675

选择性重传

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

快速重传

发送端发送了 1,2,3,4,5 几个包,然后收到远端的 ACK: 1, 3, 4, 5 ,当收到 ACK3 时, KCP

知道 2 被跳过 1 次,收到 ACK4 时,知道 2 被跳过了 2 次,此时可以认为 2 号丢失,不用

等超时,直接重传 2 号包,大大改善了丢包时的传输速度。 fastresend=2

延迟ACK

TCP为了节省带宽而采用延迟ACK机制, 不是每个数据包都对应一个 ACK 包,因为可以合并确认。也不是接收端收到数据以后必须立刻马上回复确认包。 KCP 是否延迟确认可以通过设置调节


UNA+ACK

ARQ 模型响应有两种, UNA (此编号前所有包已收到,如 TCP )和  ACK (该编号包已收

到),光用 UNA 将导致全部重传,光用 ACK 则丢失成本太高,以往协议都是二选其一,

而 KCP 协议中, 除去单独的 ACK 包外,所有包都有 UNA 信息 。

非退让流控

KCP正常模式同TCP一样使用公平退让法则,即发送窗口大小由: 发送缓存大小、接收

端剩余接收缓存大小、丢包退让及慢启动 这四要素决定。但传送及时性要求很高的小

数据时,可选择通过配置跳过后两步,仅用前两项来控制发送频率。以牺牲部分公平

性及带宽利用率之代价,换取了开着BT都能流畅传输的效果。

KCP源码流程图


kcp 调度器机制

应用层对KCP数据的收发主要关注 kcp_recv, kcp_send, 但是需要有一个kcp_update 循环loop 来处理接受到kcp的封包数据的解包回传确认包, 以及发包的数据封包等工作, 相当于是一个调度器


kcp 发送数据流程

KCP发送数据时需要发送 ikcp_send 发送数据, 这时KCP会把数据组装成 header+data的形式(可能进行分帧)发送到send_queue, send_buf(发送窗口) 从 send_queue 获取数据   通过 sendto 发送给对端, 在send_buf中缓存着 已发送 已发送待确认 未发送几种状态的数据, 假设收到对端的回传UNA=9, 9之前的数据会被从send_buf中移除


kcp 接收数据流程

1.把收到的数据放入rcv_buf 并排好序


2 数据放入rcv_queue


3 ikcp_recv 从recv_queue 读取组帧完成的数据(header 头部中的 frg字段, frg=0代表最后一个分片, 如果有切片(分帧), 切片的时候会设计好最大值)


KCP 头部解析

[0,3]conv:连接号。UDP是无连接的,conv用于表示来自于哪个 客户端。对连接的一种替代


[4]cmd:命令字。如,IKCP_CMD_ACK确认命令, IKCP_CMD_WASK接收窗口大小询问命令,IKCP_CMD_WINS接收 窗口大小告知命令,


[5]frg:分片,用户数据可能会被分成多个KCP包,发送出去


[6,7]wnd:接收窗口大小,发送方的发送窗口不能超过接收方给 出的数值


[8,11]ts:时间序列


[12,15]sn:序列号


[16,19]una:下一个可接收的序列号。其实就是确认号,收到 sn=10的包,una为11


[20,23]len:数据长度


data:用户数据,这一次发送的数据长度


cmd 命令字

cmd 作用
IKCP_CMD_PUSH 数据推送命令
IKCP_CMD_ACK 确认命令
IKCP_CMD_WASK 接收窗口大小询问命令(窗口探测)
IKCP_CMD_WINS 接收窗口大小告知命令(窗口通告)

总结

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
2月前
|
网络协议 开发者
探讨UDP协议中connect函数的作用及影响
总结来看,虽然UDP是无连接的,`connect()` 函数的使用在UDP编程中是一种可选的技术,它可以带来编程上的便利和某些性能上的改进,同时它改变的是程序逻辑上的行为,而非UDP协议本身的无连接特性。在实际应用中,根据通信模式和需求的不同,开发者可以根据情况选择是否调用 `connect()` 函数。
124 8
|
4月前
|
监控 网络协议 视频直播
UDP协议(特点与应用场景)
UDP(用户数据报协议)是传输层的一种无连接协议,具有简单高效、低延迟的特点。其主要特点包括:无连接(无需握手)、不可靠传输(不保证数据完整性)、面向数据报(独立传输)。尽管UDP不如TCP可靠,但在实时通信(如语音通话、视频会议)、在线游戏、多媒体流媒体(如直播、点播)及网络监控等领域广泛应用,满足了对速度和实时性要求较高的需求。
592 19
|
5月前
|
网络协议
为何UDP协议不可靠?DNS为何选择UDP?
总的来说,UDP和TCP各有优势,选择哪种协议取决于应用的具体需求。UDP可能不如TCP可靠,但其简单、快速的特性使其在某些场景下成为更好的选择。而DNS就是这样的一个例子,它利用了UDP的优势,以实现快速、高效的名字解析服务。
268 14
|
5月前
|
网络协议 Java 开发工具
全平台开源即时通讯IM框架MobileIMSDK:7端+TCP/UDP/WebSocket协议,鸿蒙NEXT端已发布,5.7K Stars
全平台开源即时通讯IM框架MobileIMSDK:7端+TCP/UDP/WebSocket协议,鸿蒙NEXT端已发布,5.7K Stars
292 1
|
12月前
|
存储 网络协议 算法
UDP 协议和 TCP 协议
本文介绍了UDP和TCP协议的基本结构与特性。UDP协议具有简单的报文结构,包括报头和载荷,报头由源端口、目的端口、报文长度和校验和组成。UDP使用CRC校验和来检测传输错误。相比之下,TCP协议提供更可靠的传输服务,其结构复杂,包含序列号、确认序号和标志位等字段。TCP通过确认应答和超时重传来保证数据传输的可靠性,并采用三次握手建立连接,四次挥手断开连接,确保通信的稳定性和完整性。
287 1
UDP 协议和 TCP 协议
|
8月前
|
缓存 网络协议
Jmeter如何对UDP协议进行测试?
`jmeter-plugins`是JMeter的插件管理器,用于管理和组织所有插件。访问[官网](https://jmeter-plugins.org/install/Install/)下载并放置于`lib/ext`目录下,重启JMeter后可在“选项”中看到插件管理器。
208 1
Jmeter如何对UDP协议进行测试?
|
9月前
|
XML JSON 算法
【JavaEE】——自定义协议方案、UDP协议
自定义协议,序列化,xml方案,json方案,protobuffer方案,UDP协议,校验和,比特翻转,CRC算法,md5算法
|
9月前
|
存储 网络协议 安全
用于 syslog 收集的协议:TCP、UDP、RELP
系统日志是从Linux/Unix设备及网络设备生成的日志,可通过syslog服务器集中管理。日志传输支持UDP、TCP和RELP协议。UDP无连接且不可靠,不推荐使用;TCP可靠,常用于rsyslog和syslog-ng;RELP提供可靠传输和反向确认。集中管理日志有助于故障排除和安全审计,EventLog Analyzer等工具可自动收集、解析和分析日志。
557 2
|
10月前
|
监控 网络协议 网络性能优化
网络通信的核心选择:TCP与UDP协议深度解析
在网络通信领域,TCP(传输控制协议)和UDP(用户数据报协议)是两种基础且截然不同的传输层协议。它们各自的特点和适用场景对于网络工程师和开发者来说至关重要。本文将深入探讨TCP和UDP的核心区别,并分析它们在实际应用中的选择依据。
265 3
|
10月前
|
网络协议 SEO
TCP连接管理与UDP协议IP协议与ethernet协议
TCP、UDP、IP和Ethernet协议是网络通信的基石,各自负责不同的功能和层次。TCP通过三次握手和四次挥手实现可靠的连接管理,适用于需要数据完整性的场景;UDP提供不可靠的传输服务,适用于低延迟要求的实时通信;IP协议负责数据包的寻址和路由,是网络层的重要协议;Ethernet协议定义了局域网的数据帧传输方式,广泛应用于局域网设备之间的通信。理解这些协议的工作原理和应用场景,有助于设计和维护高效可靠的网络系统。
184 4