网络协议 | TCP和UDP可靠性传输
前文: 网络协议一、协议1、HTTP协议:基于TCP连接的,主要解决如何包装数据,对应于应用层;2、TCP/UDP协议:主要解决数据如何在网络中传输,对应于传输层;3、IP协议:对应于网络层;· 在传输数据时,可以只使用传输层(TCP/IP),但是那样的话,由于没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用应用层协议,应用层协议很多,有HTTP、FTP、TELNET等等,也可以自己定义应用层协议。· web使用HTTP作传输层协议,以封装HTTP文本信息,然后使用TCP/IP做传输层协议将它发送到网络上。· TCP/IP:传输层协议,主要解决数据如何在网络中传输。TCP(TransmissionControl Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。UDP是User Datagram Protocol,一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。可靠性由上层应用实现,所以要实现udp可靠性传输,必须通过应用层来实现和控制。确认机制、重传机制、滑动窗口。1.应用数据被分割成TCP认为最适合发送的数据块。这和UDP完全不同,应用程序产生的数据长度将保持不变。由TCP传递给IP的信息单位称为报文段或段(segment)。2.当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。当TCP收到发自TCP连接另一端的数据,它将发送一个确认。TCP有延迟确认的功能,在此功能没有打开,则是立即确认。功能打开,则由定时器触发确认时间点。3.TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段(希望发端超时并重发)。4.既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。5.既然IP数据报会发生重复,TCP的接收端必须丢弃重复的数据。[2]6.TCP还能提供流量控制。TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。TCP协议用于控制数据段是否需要重传的依据是设立重发定时器。在发送一个数据段的同时启动一个重传,如果在重传超时前收到确认(Acknowlegement)就关闭该重传,如果重传超时前没有收到确认,则重传该数据段。在选择重发时间的过程中,TCP必须具有自适应性。它需要根据互联网当时的通信情况,给出合适的重发时间。这种重传策略的关键是对定时器初值的设定。采用较多的 算法 是Jacobson于1988年提出的一种不断调整超时时间间隔的动态算法。其工作原理是:对每条连接TCP都保持一个变量RTT(Round Trip Time),用于存放当前到目的端往返所需要时间最接近的估计值。当发送一个数据段时,同时启动连接的定时器,如果在定时器超时前确认到达,则记录所需要的时间(M),并修正[2]RTT的值,如果定时器超时前没有收到确认,则将RTT的值增加1倍。通过测量一系列的RTT(往返时间)值,TCP协议可以估算数据包重发前需要等待的时间。在估计该连接所需的当前延迟时通常利用一些统计学的原理和算法(如Karn算法),从而得到TCP重发之前需要等待的时间值。TCP的一项功能就是确保每个数据段都能到达目的地。位于目的主机的TCP服务对接受到的数据进行确认,并向源应用程序发送确认信息。使用数据报头序列号以及确认号来确认已收到包含在数据段的相关的数据字节。TCP在发回源设备的数据段中使用确认号,指示接收设备期待接收的下一字节。这个过程称为期待确认。源主机在收到确认消息之前可以传输的数据的大小称为窗口大小。用于管理丢失数据和流量控制。UDP它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。实现确认机制、重传机制、窗口确认机制。如果你不利用 Linux 协议栈以及上层socket机制,自己通过抓包和发包的方式去实现可靠性传输,那么必须实现如下功能:发送:包的分片、包确认、包的重发接收:包的调序、包的序号确认目前有如下开源程序利用udp实现了可靠的数据传输。分别为RUDP、RTP、UDT。RUDP 提供一组数据服务质量增强机制,如拥塞控制的改进、重发机制及淡化服务器算法等,从而在包丢失和网络拥塞的情况下, RTP 客户机(实时位置)面前呈现的就是一个高质量的 RTP 流。在不干扰协议的实时特性的同时,可靠 UDP 的拥塞控制机制允许 TCP 方式下的流控制行为。实时传输协议(RTP)为数据提供了具有实时特征的端对端传送服务,如在组播或单播网络服务下的交互式视频音频或模拟数据。应用程序通常在 UDP 上运行 RTP 以便使用其多路结点和校验服务;这两种协议都提供了传输层协议的功能。但是 RTP 可以与其它适合的底层网络或传输协议一起使用。如果底层网络提供组播方式,那么 RTP 可以使用该组播表传输数据到多个目的地。RTP 本身并没有提供按时发送机制或其它服务质量(QoS)保证,它依赖于底层服务去实现这一过程。 RTP 并不保证传送或防止无序传送,也不确定底层网络的可靠性。 RTP 实行有序传送, RTP 中的序列号允许接收方重组发送方的包序列,同时序列号也能用于决定适当的包位置,例如:在视频解码中,就不需要顺序解码。基于UDP的数据传输协议(UDP-basedData Transfer Protocol,简称UDT)是一种互联网数据传输协议。UDT的主要目的是支持高速广域网上的海量数据传输,而互联网上的标准数据传输协议TCP在高带宽长距离网络上性能很差。顾名思义,UDT建于UDP之上,并引入新的拥塞控制和数据可靠性控制机制。UDT是面向连接的双向的应用层协议。它同时支持可靠的数据流传输和部分可靠的数据报传输。由于UDT完全在UDP上实现,它也可以应用在除了高速数据传输之外的其它应用领域,例如点到点技术(P2P),防火墙穿透,多媒体数据传输等等。本文来自地址:https://blog.csdn.net/gettogetto/article/details/76736365

应用层协议如何保证UDP传输协议的数据可靠性
在网络通信质量较好的情况下,udp体现出高效率,这适合于传送少量报文的应用,其可靠性由应用程序来保证,如:接收信号后向源方返回一个回响,超时重发、数据检验等功能需应用程序来实现。虽然udp是一个不可靠的协议,但它是分发信息的一个理想协议。例如,在屏幕上报告股票市场、在屏幕上显示航空信息等等。udp也用在路由信息协议rip(routing information protocol)中修改路由表。在这些应用场合下,如果有一个消息丢失,在几秒之后另一个新的消息就会替换它。
在传输的数据里加上验证的数据,比如crc32等
数据包中加入校验码 增加数据交互,采用数据接收方应答数据发送方的机制保证数据传输的可靠性减小单个数据包的长度 等等
传输时会在你的数据前加校验码的。

如何实现自定义的可靠 UDP 协议--转载
既然已经有TCP了,为什么还需要UDP可靠?TCP是强制的可靠性传输,其在IP协议的基础上,发送端对所有的数据进行定时重传,接受端对所有的数据进行排序,以此(当然还有很多其他的机制)来实现发送端是什么样子的,接受端就能接受到什么样子的数据。但是现实中有一些场景,我们并不需要如此固执的可靠性。对于FPS游戏这种时效性要求非常高的游戏中,玩家最关心的是自己的射击结果和角色的存活与否,当有一个手雷扔过来时,对于被炸死的玩家而言,这颗手雷是必须要接收到的消息,而其他没有被炸到的玩家,仅需要看到手雷的爆炸动画或者是声音,其更关心的是自己现在的子弹,有没有将敌人爆头。我们不希望因为手雷的消息重传排队,而把射击玩家的结果确认消息延后,这对于TCP而言就力所不逮了。我们看一张图:在传输效率,传输代价和可靠性三个维度上,TCP在最左侧的这条线上,可靠性最高,但传输代价也很大,效率上不及UDP。UDP则在最右侧,只有传输效率,不保证可靠,传输代价也较低。我们如果需要在大约六角形的位置,选择一个折中的方案,那就是UDP可靠传输,即RUDP登场的时刻了。如何实现?首先,为了保证可靠性,我们需要在发送数据的时候添加重传定时器,来保证丢失的数据会被重传。重传的定时器可以定时回调发送重传的数据,也支持将接收到ACK的数据从定时器中取出。现在有了重传定时器,那每次发送数据的时候,应该给定时器设置多长的超时时间呢?最简单的可以设定一个固定的重传时间,最合理的应该针对每条传输链路的不同设置每个连接的合理时间--rto。为了找到rto时间,我们需要获取到每个数据包发送确认时间,即rtt时间,即数据从发送到接收到ACK确认之间的时间间隔。我们参照TCP的实现策略,可以给每个消息记录一个发送时间,当接收到ACK确认时,将此时的时间减去记录的发送时间就获取到了rtt时间。但这样有一个问题,当发生数据重传时接收到ACK,无法判断这个ACK是对初次发送数据的确认还是对重传数据的确认,此时只能将发生重传数据测量到的rtt时间丢弃。所以又有第二种rtt计算策略,我们可以将发送时间记录在数据头中发送出去,接受端在发送确认ACK时,将这个时间戳抄下来顺着ACK返回,这样发送端接收到ACK确认时,就能准确的知道要确认数据的发送时间,由此来计算rtt时间。有了rtt时间,我们按照TCP的标准方法《CP/TPxian详解卷一, P465》,计算rto时间。当接受到ACK确认时,我们需要将确认的数据从定时器中移除。为了提高网络链路利用率,接收端不能每次接收到数据时都立即发送ACK确认,为什么呢?传输的数据量越小,控制头占比越高,而且网络中到处都是只携带一个ACK的包在飞,会造成路由器排队。这里可以接着参考TCP的实现策略。一种是延时ACK,即接收端接收到消息时定制一个pending time,当超时时将这段时间内所有要发送的ACK组合在一起发送,还有一种是捎带ACK,即pending time未到,但恰好也有数据要发送给对端,那么就将ACK捎带在这个数据包中一起发送出去。由于接收端ACK发送都不是瞬时的,所以在上文说到的RTT计算时也需要考虑引起的计算误差。有同学要问了,你这整半天UDP可靠,还不是TCP都一样的策略?那接下来就说点和TCP不一样的东西了。我们之前都只说了一个数据包的发送接收策略,当大量数据到来时如何发送呢?不可能一下子将所有数据都发送出去。所以我们需要一个发送窗体来控制发送数据的个数,当允许发送时就拿出下一个数据包发送,这发生在接收到新的ACK确认或者发送窗体大小调整时。这里和TCP的实现不同,TCP将所有的数据平铺在一个buffer里,然后通过移动滑动窗体来控制发送数据流动。我在这里没有用到滑动窗体,而是将所有的数据包都放到一个权限队列中,按照发送两个高一级权限数据包一个低一级数据包的规则来调整发送顺序,发送窗体中只有inflight的数据包,当可以发送下一个数据包时,再从权限队列中获取。发送窗体负责对发送后的数据缓存,确认,权限队列负责给发送的数据按优先级排序。对接收端而言,也需要一个接收队列对接收到的数据包进行整理,这里我们可以根据需求的不同实现多种排队策略。如果是想得到TCP的效果,数据即有序,又可靠,那我们需要给所有到达的数据包发送ACK确认且排队,只有前一个数据包排好队,无乱序时,才能将数据反回给上层;如果只实现可靠性,不需要有序,那可以接收到一个数据包时,直接反回给上层,但是要发送ACK确认。如果只需要有序性,不需要可靠性,那可以记录目前收到最大的数据包序号,比这个序号大的数据包返回给上层,比这个序号小的直接丢弃,也不需要发送ACK,因为发送端也不会重传数据。以上就是三种不同的可靠性传输。前面我们说了很多,数据包即要携带时间戳,又要携带确认ACK,我们需要给上层发下来的数据添加一个自己的协议头以使双端来识别必要的消息,这里我们可以通过不同的控制标识组合来实现一个变长的协议头,有效利用数据包的传输数据量。其中Flag是必须的,占用4字节的长度,通过位标识后面每个块是否携带,这可以通过手动二进制序列来实现。现在对于一个传输连接而言,我们有了重传机制,确认机制,协议头封装,传输接收控制,但是网络是公共交通,我们如何遵守交通规则,不引起网络阻塞的同时有效利用网络带宽呢?这就要引入拥塞控制算法,我在这里目前使用的是BBR,还没有实现TCP的CUBIC。那为什么使用BBR算法呢?这可就是小孩儿没娘,说来话长了。简单来讲,常规的CUBIC算法通过检测丢包来判断网络拥塞,然后通过控制发送窗体的大小来控制传输在网络中的数据量。大家想一下网络中的传输情况:CUBIC算法在第3阶段检测到丢包,开始减小发送窗体的大小,以收缩网络中传输的数据量,消化路由器排队队列,但是这时已经晚了!在没有发生丢包之前,链路中已经被数据包压的苦不堪言,发送数据的RTT时间已经非常慢。什么时候是链路利用率最高的时候呢?即在2阶段路由器即将有排队情况出现的时候,这时RTT时间最小,但是链路上已经有足够的数据在飞。CUBIC算法还有一个问题是其控制的输出变量只有发送窗体的大小,当发送窗体增大,应用层有数据到来时,会一股脑的将可发送的数据量全部发送出去。现实生活中的十字路口,大家都会遵守交通规则,通过红绿灯控制来保证每个路口都定时的可以让一些车辆通过,然而到了网络世界里一切都变的蛮不讲理,在此路口车很多的情况下,所有车都一个接一个的驶出,而不管交叉路口还有没有别的车等待,这是不对的。所以BBR算法不仅需要控制发送窗体的大小来控制发送的数据量,还通过RTT时间和传输的数据量来计算一个数据的发送速度,通过控制数据流发送的时间间隔,来实现按一定速率发送数据。具体BBR算法是如何实现的,那就是另外一篇长篇大论了,本文不再细说。到目前为止,关于可靠性和传输效率的机制我们基本已经介绍完成,接下来说下传输的建立和连接。传输建立时并没有参考TCP的三次握手,依照UDP的简单粗暴,发送端只管发送数据,接收端能收到算建立了连接,没有接收到则发送端超时。因为我们的协议实现在应用层,没有进程启动的时候也无法发送RST给对端。连接断开时基本参考了TCP的四次挥手实现,继续保留了TIME_WAIT状态来保证网络中上一个连接的数据包不会发送到现任连接上。关于实现的大体机制终于讲完,其他还有一些数据包序列号标识,随机首个序列号,flow queue,pacing实现等细节没有展开,但核心的可靠实现基本就是以上,接下来画一张数据流向图:在socket上有一个Filters process,这是一个过滤器责任链,所有收发的数据都要通过这个过滤器责任链,其可以对传输的包体进行压缩,加密等处理,我在这里实现了snappy对传输数据的压缩过滤器,额外线程通知过滤器,和大数据包的拆分过滤器。通过双向链表管理所有的过滤器模块,可以很方便的嵌入额外的过滤器过程,在这里也可以实现一些熔断转发之类服务治理相关的过滤器。

UDP使用什么提供可靠性
使用udp协议的软件,通过应用程序本身来保证传输的正确性,而且即使是udp协议,现在的网络需要重传的数据包时很少的
UDP无连接的传输层协议,可靠性由应用层来实现。

UDP如何转为可靠协议
需要在应用层,也就是UDP的上层完成消息的检查。UDP协议本身无法完成这种。
在发送的字符串前面加个文件头,收到的时候自己解析即可
你问面试官知道吗?

本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/47510.html。