可靠UDP浅入

传输协议的可靠性

  • TCP协议(Transmission Control Protocol,传输控制协议)为应用层提供可靠的、面向连接的和基于流(stream)的服务。使用超时重传、数据确认等方式来确保数据包被正确发送至目的地。
  • UDP(User Datagram Protocol,户数据报协议)是无连接的,面向消息的数据传输协议,与TCP相比,有两个致命的缺点:
    (1)数据包容易丢失;
    (2)数据包无序。
    UDP是传输层的协议,不可靠,如果物理层,数据链路层或网络层能提供可靠性的话,那么UDP就可以利用下面各层的可靠性实现自己的可靠性;然而,UDP是不可靠的,也就是说它下面的各层并不能保证UDP可靠性,所以只能靠上面的应用层来保证可靠性。所以必须制定上层的协议,包括:流控机制、超时机制、重排机制、重传机制。
目前最常用的两个协议就是TCP和UDP,通过它们两个的特性能发现互有缺点,在不同场景可以选择不同的协议去通信,随着网络的传输速度越来越快,5G时代的到来,以前一直被我们诟病的UDP也逐渐被挖掘其价值,特别是在实时性要求很高的应用里面,UDP显得尤不可缺,随口说一句,像《王者荣耀》这种实时性游戏,UDP在里面发挥着巨大的作用,只不过为了保证UDP的可达和有序,腾讯对UDP进行了补充,不过要想能随意的就能对这种通用协议进行改动和补充这可是需要非常强大能力水平,例如BAT这种一线大厂。



可靠UDP适用场景 问题来了,既然想要使用可靠的UDP,那就必须补充一些TCP的流控机制、超时机制、重排机制、重传机制,那么这和TCP有什么区别,为何不直接使用TCP更省事呢?
  • 网速的提升给UDP稳定性提供可靠网络保障。CDN服务商Akamai(NASDAQ: AKAM)报告从2008年到2015年7年时间,各个国家网络平均速率由1.5Mbps提升为5.1Mbps,网速提升近4倍。网络环境变好,网络传输的延迟、稳定性也随之改善,UDP的丢包率低于5%,如果再使用应用层重传,能够完全确保传输的可靠性。
  • 对比测试结果UDP性能优于TCP。为了提升浏览速度,Google基于TCP提出了SPDY协议以及HTTP/2。Google在Chrome上实验基于UDP的QUIC协议,传输速率减少到100ms以内。
Google采用QUIC后连接速率能有效提升75%。
Google搜索采用QUIC后页面加载性能提升3%。
YouTube采用QUIC后重新缓冲次数减少了30%。可靠UDP浅入
文章图片

  • TCP设计过于冗余,速度难以进一步提升。TCP提供了过多的保护,在及时性上做了很多的妥协,比如:控制微包(Nagle算法),延时ACK,流量控制,超时重传等,这些设计严重影响了Tcp的速度和及时性。由于TCP内置在系统协议栈中,极难对其进行改进。
  • 寄希望于业务逻辑上允许信息丢失。UDP它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。需要对 UDP 的不可靠传输进行适当的改进,以减少数据的丢失。应用进程可以在不影响应用的实时性的前提下,增加一些提高可靠性的措施,如采用前向纠错或重传已丢失的报文
  • TCP 是个基于公平性的可靠通信协议,但是在一些苛刻的网络条件下 TCP 要么不能提供正常的通信质量保证,要么成本过高。为什么要在 UDP 之上做可靠保证,究其原因就是在保证通信的时延和质量的条件下尽量降低成本。
  • TCP是强制的可靠性传输,其在IP协议的基础上,发送端对所有的数据进行定时重传,接受端对所有的数据进行排序,以此(当然还有很多其他的机制)来实现发送端是什么样子的,接受端就能接受到什么样子的数据。但是现实中有一些场景,我们并不需要如此固执的可靠性。
  • 当服务器设计容量是海量级的应用,一台服务器要同时容纳十几万的并发连接,因此服务器端只有采用UDP协议与客户端进行通讯才能保证这种超大规模的服务。比如QQ,如果用tcp的话,服务端会接受海量连接,每个连接要维持一个连接,占用很多资源,tcp的包和udp的包没有任何不同,只不过tcp的可靠性由操作系统保证,udp可靠性由腾讯程序员保证,qq聊天只是字符,数据量很小,所以不用tcp的复杂流量控制。
相对于TCP的强制性可靠传输,UDP更像是一张白纸,可以实现自己需要的可靠性。实现起来和TCP有一些相同的策略,但可以更自由的实现一些TCP没有的功能。要注意的是,如果要想建立一个完全可靠的UDP,那就可以说只不过是另一个TCP罢了,没有什么太大的意义,可靠UDP只不过是实时性与可靠性之间的一种折中方案,鱼与熊掌不可兼得,这就是软件工程的抉择信条。
采用UDP有3个关键点:
  1. 网络带宽需求较小,而实时性要求高;
  2. 大部分应用无需维持连接;
  3. 需要低功耗。



UDP分片原理 1.对应用层的数据进行分片,以满足MTU传输的要求
2.在发送端给分片编号,在接收端重组分片,解决乱序数据包重组的问题
UDP传输应用层需注意的问题
1.数据包确认机制,可以对数据报进行确认和排序
2.数据包重发机制,能避免数据报丢失
3.尽量不发送大于路径MTU的数据包
4.处理数据包重排


所以,总的来看,就是需要在应用层实现一个简单版的TCP,是不是觉得很好笑,放着好好的轮子不用,非要自己造一个。

UDP和MTU的关系
  • MTU,最大传输单元(Maximum Transmission Unit)是指通信协议的某一层上面所能通过的最大数据包大小(以字节为单位),最大为1500字节(局域网发送)。
  • 单个UDP传输的最大内容1472(1500-20-8)字节,但由于不同的网络中转设备设置的MTU值并不相同。Internet上的标准MTU值为576字节(公网),建议在进行Internet的UDP编程时,最好将UDP的数据长度控制在548字节(576-20-8)以内。
可靠UDP浅入
文章图片




UDP分片设计 可靠UDP浅入
文章图片

可靠UDP浅入
文章图片

大数据,分块传输,接收后通过附加信息组合。
可靠UDP浅入
文章图片




如何提高UDP的可靠性 本端:首先在UDP数据报定义一个首部,首部包含确认序列号和时间戳,时间戳是用来计算RTT(数据报传输的往返时间),从何计算出合适的RTO(重传的超时时间)。然后以等-停的方式发送数据报,即收到对端的确认之后才发送下一个的数据报。当时间超时,本端重传数据报,同时RTO扩大为原来的两倍,重新开始计时。
对端:接受到一个数据报之后取下该数据报首部的时间戳和确认序列号,并添加本端的确认数据报首部之后发送给对端。根据此序列号对已收到的数据报进行排序并丢弃重复的数据报。



UDP分片的代码实现 还在开发中,待完善



巨人的肩膀
从他人的工作中汲取经验来避免自己的错误重复,正如我们是站在巨人的肩膀上才能做出更好的成绩。
【可靠UDP浅入】https://segmentfault.com/a/1190000018902719
https://www.cnblogs.com/zhangbing12304/p/11016921.html
https://blog.csdn.net/bobozai86/article/details/87518617
https://www.cnblogs.com/home123/p/7499608.html
https://www.cnblogs.com/lixiang-share/p/7152870.html
https://blog.csdn.net/pangyemeng/article/details/50387078
https://www.jianshu.com/p/4d12ad2e7500
https://mp.weixin.qq.com/s/fZ_QeTsS7kbZnfUL-A3UUA

    推荐阅读