ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

UDP的可靠性传输

2021-11-25 00:01:29  阅读:189  来源: 互联网

标签:UDP 可靠性 重传 TCP 传输 kcp 数据 KCP


文章目录

UDP和TCP的区别

Tcp和udp都是属于TCP/IP协议(传输层协议)。

TCP

TCP(Transmission Control Protocol,传输控制协议)是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接。 一个TCP连接必须要经过三次握手,断开连接时需要四次挥手。

TCP的可靠性主要体现在什么方面呢?
1. 应用数据被分割成TCP认为最合适发送的数据块。
这个和UDP完全不同,应用程序将产生的数据报长度将保持不变。由TCP传递给IP的信息单位称为报文段或段。最大报文段(MSS)表示TCP传往另一端的最大块数据的长度。连接建立时,双方都需要通告自己的MSS。默认情况下MSS的值为536字节(可以加上20字节的IP首部和20字节的TCP首部)。对于一个以太网,最大的MSS可达到1460字节(1500(MTU) - 20(IP) - 20(TCP))。

2. 当TCP发出一个段之后,它启动一个定时器,等待目的端确认收到这个报文段,如果不能及时收到一个确认,将重发这个报文段。
3. 当TCP收到另一端的数据,他将发送一个确认。这个确认不是立即发送,而是延迟几分之一秒。
4. TCP将保持它首部和数据的校验和。这个是一个端到端的检测,目的是检测数据在传输时的任何变化,如果有收到段的检验和有差错,tcp将丢弃这个报文段和不确认收到此报文段。
5. 既然tcp报文段作为ip数据报来传输,而ip数据报的到达可能会失序,因此tcp报文段的到达可能会失序。如果必要,tcp将对收到的数据进行重新排序。
6. ip数据报会发生重复,tcp的接收端必须丢弃重复的数据。
7. TCP提供流量控制。

TCP头部结构

UDP

UDP(UserDatagramProtocol)是一个简单的面向消息的传输层协议,尽管UDP提供标头和有效负载的完整性验证(通过校验和),但它不保证向上层协议提供消息传递,并且UDP层在发送后不会保留UDP 消息的状态。因此,UDP有时被称为不可靠的数据报协议。如果需要传输可靠性,则必须在用户应用程序中实现。
在这里插入图片描述

推荐免费的直播课程: https://ke.qq.com/course/417774?flowToken=1040690

为什么要使用UDP传输可靠性数据

UDP(User Datagram Protocol)传输与IP传输非常类似,它的传输方式也是"Best Effort"的,所以UDP协议也是不可靠的。我们知道TCP就是为了解决IP层不可靠的传输层协议,既然UDP是不可靠的,为什么不直接使用IP协议而要额外增加一个UDP协议呢?

  1. 一个重要的原因是IP协议中并没有端口(port)的概念。IP协议进行的是IP地址到IP地址的传输,这意味者两台计算机之间的对话。但每台计算机中需要有多个通信通道,并将多个通信通道分配给不同的进程使用。一个端口就代表了这样的一个通信通道。UDP协议实现了端口,从而让数据包可以在送到IP地址的基础上,进一步可以送到某个端口。
  2. 对于一些简单的通信,我们只需要“Best Effort”式的IP传输就可以了,而不需要TCP协议复杂的建立连接的方式(特别是在早期网络环境中,如果过多的建立TCP连接,会造成很大的网络负担,而UDP协议可以相对快速的处理这些简单通信)
  3. 在使用TCP协议传输数据时,如果一个数据段丢失或者接收端对某个数据段没有确认,发送端会重新发送该数据段。TCP重新发送数据会带来传输延迟和重复数据,降低了用户的体验。对于迟延敏感的应用,少量的数据丢失一般可以被忽略,这时使用UDP传输将能够提升用户的体验。

UDP将数据从源端发送到目的端时,无需事先建立连接,没有使用TCP中的确认技术或滑动窗口机制,因此UDP不能保证数据传输的可靠性,也无法避免接收到重复数据的情况。

UDP传输的可靠性由应用层负责,由应用程序根据需要提供报文ACK机制、重传机制、序号机制、重排机制和窗口机制。这些TCP已经都具备了。

如何使用UDP传输可靠性数据

这里我们主要介绍一种开源UDP的可靠性方案KCP:https://github.com/skywind3000/kcp
KCP主要的优势体现在以下方面:

  1. 以10%-20%带宽浪费的代价换取了比 TCP快30%-40%的传输速度。
  2. RTO翻倍vs不翻倍:TCP超时计算是RTOx2,这样连续丢三次包就变成RTOx8了,十分恐怖,而KCP启动快速模式后不x2,只是x1.5(实验证明1.5这个值相对比较好),提高了传输速度。
  3. 选择性重传 vs 全部重传: TCP丢包时会全部重传从丢的那个包开始以后的数据, KCP是选择性重传,只重传真正丢失的数据包。
  4. 快速重传(跳过多少个包马上重传)(如果使用了快速重传,可以不考虑RTO))
  5. 发送端发送了1,2,3,4,5几个包,然后收到远端的ACK: 1, 3, 4, 5,当收到ACK3时, KCP知道2被跳过1次,收到ACK4时,知道2被跳过了2次,此时可以认为2号丢失,不用等超时,直接重传2号包,大大改善了丢包时的传输速度。
  6. UNA vs ACK+UNA:ARQ模型响应有两种, UNA(此编号前所有包已收到,如TCP)和ACK(该编号包已收到),光用UNA将导致全部重传,光用ACK则丢失成本太高,以往协议都是二选其一,而 KCP协议中, 除去单独的 ACK包外,所有包都有UNA信息。
  7. 非退让流控:KCP正常模式同TCP一样使用公平退让法则,即发送窗口大小由:发送缓存大小、接收端剩余接收缓存大小、丢包退让及慢启动这四要素决定。但传送及时性要求很高的小数据时,可选择通过配置跳过后两步,仅用前两项来控制发送频率。以牺牲部分公平性及带宽利用率之代价,换取了开着BT都能流畅传输的效果。

名词说明:
用户数据:应用层发送的数据,如一张图片2Kb的数据
MTU:最大传输单元。即每次发送的最大数据
RTO: Retransmission TimeOut,重传超时时间。
cwnd:congestion window,拥塞窗口,表示发送方可发送多少个KCP数据包。
与接收方窗口有关,与网络状况(拥塞控制)有关,与发送窗口大小有关。
rwnd:receiver window,接收方窗口大小,表示接收方还可接收多少个KCP数据包
snd_queue:待发送KCP数据包队列
snd_nxt:下一个即将发送的kcp数据包序列号
snd_una:下一个待确认的序列号

KCP的使用方式

  1. 创建 KCP对象: ikcpcb *kcp = ikcp_create(conv, user);
  2. 设置传输回调函数(如UDP的send函数): kcp->output = udp_output;
  3. 真正发送数据需要调用sendto
  4. 循环调用 update: ikcp_update(kcp, millisec);
  5. 输入一个应用层数据包(如UDP收到的数据包) :ikcp_input(kcp,received_udp_packet,received_udp_size);
  6. 我们要使用recvfrom接收,然后扔到kcp里面做解析
  7. 发送数据: ikcp_send(kcp1, buffer, 8); 用户层接口
  8. 接收数据: hr = ikcp_recv(kcp2, buffer, 10);

在这里插入图片描述

kcp配置模式

  1. 工作模式: int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
  • nodelay :是否启用 nodelay模式, 0不启用; 1启用。
  • interval :协议内部工作的 interval,单位毫秒,比如 10ms或者 20ms
  • resend :快速重传模式,默认0关闭,可以设置2(2次ACK跨越将会直接重传)
  • nc :是否关闭流控,默认是0代表不关闭, 1代表关闭。
    普通模式: ikcp_nodelay(kcp, 0, 40, 0, 0);
    极速模式: ikcp_nodelay(kcp, 1, 10, 2, 1)
  1. 最大窗口: int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd);
    该调用将会设置协议的最大发送窗口和最大接收窗口大小,默认为32,单位为包。
  2. 最大传输单元: int ikcp_setmtu(ikcpcb *kcp, int mtu);
    kcp协议并不负责探测 MTU,默认 mtu是1400字节
  3. 最小RTO:不管是 TCP还是 KCP计算 RTO时都有最小 RTO的限制,即便计算出来RTO为
    40ms,由于默认的 RTO是100ms,协议只有在100ms后才能检测到丢包,快速模式下为
    30ms,可以手动更改该值: kcp->rx_minrto = 10;

kcp的协议头

在这里插入图片描述

  • conv:连接号。 UDP是无连接的, conv用于表示来自于哪个
    客户端。对连接的一种替代
  • cmd:命令字。如, IKCP_CMD_ACK确认命令,
    IKCP_CMD_WASK接收窗口大小询问命令,
    IKCP_CMD_WINS接收窗口大小告知命令,
  • frg:分片,用户数据可能会被分成多个KCP包,发送出去
  • wnd:接收窗口大小,发送方的发送窗口不能超过接收方
    给出的数值
  • ts:时间序列
  • sn:序列号
  • una:下一个可接收的序列号。其实就是确认号,收到
    sn=10的包, una为11
  • len:数据长度
  • data:用户数据

test kcp代码: https://github.com/birate-wz/wz_utils/tree/main/kcp

标签:UDP,可靠性,重传,TCP,传输,kcp,数据,KCP
来源: https://blog.csdn.net/u014183456/article/details/119361294

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有