分享

UDP 实现可靠传输

 好汉勃士 2022-08-10 发布于广东

UDP头部结构

UDP是面向数据报的简单传输层协议,不需要建立服务器与客户端的连接就能传输数据报,数据报是指从发送方到接收方的一个信息单元。正因为不需要建立连接所以它不能及时的返回传输状态,也不能确定数据是否到达发送方。
UDP头部的结构:

  • 16位源端口号:标识发送方应用程序
  • 16位目的端口号:标识接收方应用程序
  • 16位UDP数据报长度:表示发送方传输数据报的大小
  • 16位检验和:校验数据报是否完整,不完整是重发数据
    UDP首部共为8字节 (16+16+16+16)/ 8 = 8字节
    UDP头部结构图如下:

TCP头部结构

TCP是面向连接的协议,因此数据传输之前必须先建立连接,通过连接来传输数据,当数据传输完成后断开连接,因此TCP相比UDP可以保证数据的可靠稳定。
TCP头部的结构:

  • 16位源端口号:标识发送方应用程序
  • 16位目的端口号:标识接收方应用程序
  • 32位序列号:数据按照序列号传输,如果接收方接收后的数据序列号出现错误,可以根据此序列号进行重排
  • 32位确定序列号:接收方接收到信号后,对发送方进行确认,此确定号为接收到的序列号+1
  • 4位头部长度:标识TCP头部有多少个4字节,最大为1111(15)
  • 6位保留长度:暂时没有标明用途
  • 6位标志:
    URG:紧急指针,让中间层尽快处理数据
    ACK:确定信号,让确认序列号有效
    PSH:push操作,数据到达接收方后立即送入应用程序,不进入缓存区
    RST:复位连接,用来复位错误的连接
    SYN:同步信号,在建立连接的三次握手中会用到
    FIN:发送方数据发送完成,在断开连接的四次挥手中会用到
  • 16位窗口大小:是接收方用于告诉发送方TCP缓冲区还能容纳多少字节
  • 16位检验和:检验数据在发送过程中是否损坏
  • 16位紧急指针:当URG为1时,表示此序列号开始到此序列号+紧急指针之间的数据为紧急数据
    TCP头部通常占20个字节,也是必有字节(可能TCP头部超过20字节但以上自己必有)(16+16+32+32+4+6+1+1+1+1+1+1+16+16+16)/ 8 = 20字节
    TCP头部结构如下图:

概述

UDP不属于连接协议,具有资源消耗少,处理速度快的优点,所以通常音频,视频和普通数据在传送时,使用UDP较多,因为即使丢失少量的包,也不会对接受结果产生较大的影响。

传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。

最简单的方式是在应用层模仿传输层TCP的可靠性传输。下面不考虑拥塞处理,可靠UDP的简单设计。

  • 1、添加seq/ack机制,确保数据发送到对端
  • 2、添加发送和接收缓冲区,主要是用户超时重传。
  • 3、添加超时重传机制。

详细说明:送端发送数据时,生成一个随机seq=x,然后每一片按照数据大小分配seq。数据到达接收端后接收端放入缓存,并发送一个ack=x的包,表示对方已经收到了数据。发送端收到了ack包后,删除缓冲区对应的数据。时间到后,定时任务检查是否需要重传数据。

目前有如下开源程序利用udp实现了可靠的数据传输。分别为RUDP、RTP、UDT

开源程序

1、RUDP(Reliable User Datagram Protocol)

RUDP 提供一组数据服务质量增强机制,如拥塞控制的改进、重发机制及淡化服务器算法等,从而在包丢失和网络拥塞的情况下, RTP 客户机(实时位置)面前呈现的就是一个高质量的 RTP 流。在不干扰协议的实时特性的同时,可靠 UDP 的拥塞控制机制允许 TCP 方式下的流控制行为。

2、RTP(Real Time Protocol)

RTP为数据提供了具有实时特征的端对端传送服务,如在组播或单播网络服务下的交互式视频音频或模拟数据。

应用程序通常在 UDP 上运行 RTP 以便使用其多路结点和校验服务;这两种协议都提供了传输层协议的功能。但是 RTP 可以与其它适合的底层网络或传输协议一起使用。如果底层网络提供组播方式,那么 RTP 可以使用该组播表传输数据到多个目的地。

RTP 本身并没有提供按时发送机制或其它服务质量(QoS)保证,它依赖于底层服务去实现这一过程。 RTP 并不保证传送或防止无序传送,也不确定底层网络的可靠性。 RTP 实行有序传送, RTP 中的序列号允许接收方重组发送方的包序列,同时序列号也能用于决定适当的包位置,例如:在视频解码中,就不需要顺序解码。

3、UDT(UDP-based Data Transfer Protocol)

基于UDP的数据传输协议(UDP-basedData Transfer Protocol,简称UDT)是一种互联网数据传输协议。UDT的主要目的是支持高速广域网上的海量数据传输,而互联网上的标准数据传输协议TCP在高带宽长距离网络上性能很差。

顾名思义,UDT建于UDP之上,并引入新的拥塞控制和数据可靠性控制机制。UDT是面向连接的双向的应用层协议。它同时支持可靠的数据流传输和部分可靠的数据报传输。由于UDT完全在UDP上实现,它也可以应用在除了高速数据传输之外的其它应用领域,例如点到点技术(P2P),防火墙穿透,多媒体数据传输等等。

可靠UDP传输协议总结

TCP/IP协议栈中,TCP和UDP属于传输层,负责实现数据的传输。其中TCP是面向连接的和基于单个字节流的、保证顺序的可靠传输协议,UDP是无连接的、不可靠的、面向报文的协议。

在实际应用中,TCP由于简单可靠,被大部分应用层协议使用,特别是HTTP,所以占据了互联网流量的主要部分。由于TCP的广泛应用,并且是实现在操作系统中,在参数和算法调整上比较受限,难以进行一些激进的改进和定制。另外TCP的NAT穿越比较困难,一些P2P应用也只能使用UDP,所以就有了各种各样的可靠UDP协议。

可靠传输的原理

实现可靠传输一般有两种途径,一是基于ARQ(Automatic Repeat reQuest)的确认和重传机制,二是使用前向纠错(FEC)。

FEC是纠删码在通信中的应用,一般在链路层用的比较多,特别是无线通信中(包括WiFi,移动通信、卫星通信等)。可靠UDP传输主要还是依靠重传机制,个别协议会用FEC作为辅助手段,所以本文中主要介绍重传相关的技术。

ARQ

ARQ包括停等式、回退N帧、选择重传等机制。由于停等式的效率太低,TCP和可靠UDP协议一般使用的是基于回退N帧机制和滑动窗口协议的连续式ARQ,TCP后来也引入了SACK,以提高性能。

滑动窗口

滑动窗口是一种流量控制技术,接收方可以通过反馈来指示发送方调节数据发送的速度。TCP中使用滑动窗口协议来控制发送的数据量,达到理想的传输速度。

拥塞算法

TCP早期没有拥塞控制,直到1986年由于拥塞导致网络瘫痪,所以拥塞控制被引入到TCP中。拥塞算法主要是计算和调整接收窗口、发送窗口、拥塞窗口的大小,从而控制传输速度,既充分利用带宽,又避免网络出现拥塞。

最早的拥塞算法是Tahoe,后来的改进版有Reno、NewReno、BIC、CUBIC等。Linux在2.6.8之前使用的是Reno/NewReno,2.6.8到2.6.18之间使用BIC,2.6.19开始使用CUBIC。

拥塞算法的核心机制有:

  • 慢启动

在连接刚建立时接收窗口以指数方式增加,直到达到慢启动的阀值,或者是遇到丢包,开始进入拥塞回避阶段。

  • 拥塞回避

在此阶段会使用AIMD(Additive Increase Multiplicative Decrease)方式调整窗口大小,通过线性增加和指数衰减,逐渐逼近和收敛到一个理想值,从而达到充分利用带宽但又不引起拥塞的状态。

  • 快重传

发送方如果收到连续3次重复的ACK确认,就认为出现了丢包,而不需要等到重传计时器超时。这样可以更早的检测到丢包,提高算法效率。

  • 快恢复

Tahoe检测到丢包后,会回到初始状态,然后进入慢启动阶段,导致传输效率太低。Reno对此作了改进,在检测到丢包后,直接进入拥塞回避阶段,将窗口大小调整为原来的一半,避免了慢启动的开销。

拥塞算法分类

TCP的拥塞算法有很多种,按照拥塞检测的机制,可以分为三类:

  • 基于丢包

路由器和交换机在要转发的报文超过负载时会丢弃部分报文,所以丢包可以作为网络出现拥塞的一个标志,这也是TCP中主流的拥塞检测机制。从最早的Tahoe和改进版的Reno、NewReno、HSTCP、STCP、BIC、CUBIC等,都是基于丢包的,也是主流的拥塞检测机制。

  • 基于延时

现在的路由器和交换机的缓存比较大,对于超出负载的报文会先缓存起来,而不是立即丢弃。直到负载超过缓存大小,才会丢弃报文。所以当网络出现拥塞时,并不是马上丢包,而有报文丢失时,网络的拥塞已经比较严重。这样,前面基于丢包的拥塞检测机制就不够准确,于是,就有了基于延时的检测算法。

虽然这类算法可以更早的检测出拥塞,使得整个网络更有效率,但在跟基于丢包的算法竞争时,却由于过早的避让,导致性能较差,无法保证算法的公平性,所以影响了它们的应用。

这类的算法有Vegas和Fast TCP,其中Fast TCP是一种商业方案,有专利保护,在一些单边加速的场景中有应用。Vegas由于公平性的问题,没有被广泛使用。

Google新推出的BBR算法,虽然也可以归为基于延时类的,但跟传统算法有较大区别。传统算法通过AIMD来逼近理想传输速度,效率较低,而且受丢包和抖动的影响较大。BBR通过RTT和带宽乘积(BDP)来作为调整发送窗口的基础,避免了这些问题,从而提高性能和避免拥塞。

  • 显式拥塞通知(Explicit Congestion Notification)

通过IP头中2个bit的ECN标识和TCP头中的ECN-Echo位,可以在各节点以及中间设备之间显式的传递拥塞信号,从而达到避免拥塞的目的。不过由于一些终端和中间设备(路由器、交换机、网关等)并不支持ECN,导致ECN并没有广泛应用。

可靠UDP协议

UDT(UDP-based Data Transfer Protocol)

UDT的主要目的是支持高速广域网上的海量数据传输,所以除了在UDP之上实现类似TCP的协议和算法之外,UDT还对TCP的拥塞算法做了一些细节上的调整,包括Negative-ACK(NAK)、ACK to ACK(ACK2)、基于对数的动态AIMD等。不过UDT的重传效率较低,无效报文,实际效果并不理想。

KCP

KCP是一个很简单的ARQ的实现,包括选择重传和快重传等机制,对上层提供一个可靠的字节流。应用层可以使用多流复用的框架来实现对多个流的支持。另外,KCP增加了可配置启用的加密和FEC选项,FEC用的是Reed-Solomon纠删码,例如可以配置发送10%的冗余数据,来减少丢包时需要的重传,从而降低数据传输的延时。

QUIC

QUIC是Google实现的一种可靠UDP传输协议,并且已经被选择作为HTTP/3的基础。它的特点有:

  • 内建安全性,集成TLS
  • 连接建立过程和TLS协商过程合并,减少往返请求次数,提高连接速度
  • 集成多种拥塞算法,包括最新的BBR
  • 多流支持,每个流有独立的拥塞控制,避免单个流中的丢包阻塞其它所有流(Head-of-line Blocking问题),更好的支持类似HTTP/2中的乱序请求
  • 连接迁移:QUIC可以通过连接ID来唯一标识一个连接,当用户在有线、无线、移动网络之间切换时,可以保持上层连接的有效性,不需要再进行重连。

另外,早期的QUIC还使用了一种基于异或的FEC算法,不过在新版本中已经去掉。

uTP

uTP是BitTorrent中新增加的一种UDP传输协议,主要特点是使用了LEDBAT(Low Extra Delay Background Transport)拥塞算法。这种算法基于延时来检测网络拥塞,可以更早的探测到拥塞和更早的以及更大幅度的进行避让,从而避免影响用户上网操作的进行,保持后台下载跟前台操作的和平共处。

FASP(Aspera)

FASP是Aspera公司(已被IBM收购)的私有UDP解决方案,提供加密的可靠传输,拥塞算法估计是类似BBR,直接使用RTT和带宽来作为调节速度的参考。但FASP主要用于高速的文件传输,所以不需要保证报文的顺序,避免乱序重组时占用的内存开销,而且也避免了因为内存有限而丢弃的部分乱序报文,从而减少不必要的重传,提高传输速度。也就是说,完全避免了Head-of-line Blocking问题。

SCTP(Stream Control Transmission Protocol,流控制传输协议)

准确的说,SCTP不是一种可靠UDP协议,而是一种跟TCP/UDP平级的传输层协议,是IETF在2000年指定的标准协议。目前Linux和部分UNIX已经集成,Windows和Mac需要使用第三方包来实现。SCTP最初主要用于电信系统,此外,WebRTC中的DataChannel也用到这个协议。它的特点有:

  • 跟TCP一样面向连接,提供可靠传输
  • 跟UDP一样面向消息
  • 多流支持
  • 每个流可以配置成接受有序或无序的消息
  • Multi-Homing:可以配置多个地址,利用多条网络传输通道
  • 更好的安全性:要求四次握手,避免TCP的SYN Flooding攻击

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多