tcp怎么保证网络可靠传输(TCP怎么保证可靠传输)

      最后更新:2023-07-10 22:46

      TCP是如何实现可靠传输的?

      在计算机网络的经典五层协议中,TCP属于运输层,实现了进程间的通信,保证了数据的可靠传输,属于计算机网络协议族中最重要的协议之一,那么TCP是如何实现可靠数据传输的呢?运输层的进程间通信是通过socket实现的,socket是一个抽象的概念,在Linux系统中以文件的形式存在。网络层通过IP来区分主机,运输层则增加了端口的概念来区分进程。TCP协议中使用目标IP、目标端口、源IP、源端口来定义一个socket,只需要在运输层的报文头部附加上这些信息,目标主机就会知道数据要发送那个socket,对应监听该socket的进程就可以收到数据进行处理。TCP报文包括首部和数据部分,首部附加了TCP报文的信息,首部长度固定部分为20字节,还有40字节的可选部分,具体如下图所示:其中几个关键字段的作用如下:网络层只管尽可能将数据从一个主机发送到另一个主机,并不保证数据可靠到达,由于网络环境总是不稳定的,可能存在丢包、差错等请求,TCP则通过一系列的机制在运输层保证了数据的可靠传输。网络传输可能发生的异常情况和解决方法:要实现可靠传输,最简单的方法就是发送方发送一个报文,接收方收到报文后发送确认报文表示我收到了,你可以发下一个了,传输模型如下:这种方式保证可靠传输称为停止等待协议,这种方式缺点也很明显,效率非常低。为了提高传输效率,充分利用带宽,发送方会连续的发送数据包,如下图所示:客户端不等收到前一个包的确认报文就开始不断的发下一个包,这样可以充分利用网络带宽,提高传输效率,但是于此同时也带来了另外的问题,那么TCP是如何解决这些问题的?累计确认:网络中充斥着大量的发送包和确认回复报文,这些数据只是为了确认报文到达,并不是实际需要传输的数据。是不是一定要每一个报文都要发一个回复确认的报文呢,TCP采用了累计确认的方法:接收方在累计收到了一定量的数据包后发送一个确认报文告诉发送方在此之前的数据包都已经收到了,这样便可以减少确认报文的数量,提高带宽利用率。GBN(回退n步):如果发生丢包的情况,在连续ARQ中,如果接受方收到了123 567个字节,编号为4字节的包丢失了,按照累计确认只能发送3的确认回复,567都要丢掉,因为发送发会进行重传。选择确认ACK:在TCP报文头部的选项字段部分设置已收到的报文,每一段用两个边界来确定,比如上述情况可以用[1,3]和[5,7]来表示,客户端就会根据选项只重传丢失的数据段。因为接收方读数据的能力有限,发送发不能一直发送报文直到把缓冲区所有数据发送完,这样会导致接收方无法接收丢弃掉数据包,发送方收不到确认认为超时又会继续重传,产生了大量无用数据的重传。对此情况TCP使用滑动窗口来解决,基本模型如下:滑动窗口机制实现了TCP的流量控制,不至于发送太快导致太多的数据丢弃和重传。为了避免网络过分拥挤导致丢包严重,传输效率低,TCP实现了拥塞控制机制,拥塞控制的解决办法本质上是流量控制,控制发送方发送的速度,而上文提到流量控制是通过滑动窗口来实现的,所以最终也是通过调整发送方的滑动窗口大小来实现的。拥塞控制的几个重要的概念:慢启动、拥塞避免、快恢复、快重传Reno算法是比较常见的TCP实现的拥塞控制算法,其他拥塞算法还有Tahoe(已废弃不用)、New Reno等,通过拥塞控制算法可以很大程度避免网络拥挤。【书籍】计算机网络:自顶向下方法【码农有道】 这一篇TCP总结请收下
      TCP是如何实现可靠传输的?

      TCP协议通过哪些方法保证数据传输的可靠性

      TCP协议支持数据报传输可靠性的主要方法是确认、超时、重传、校验和以及流量控制。 (1)校验和——每个TCP报文段都包括检验和字段,校验和用来检查报文段是否出现传输错误,如果报文段出现传输错误,TCP检查出错就丢弃该报文段。(2)确认——接收端检查报文是否出错,发现出错时就丢弃,不发确认;而发送端TCP就通过检查接收端的确认,判断发送的报文段是否已经正确到达目的地。 (3)超时——发送端根据发出的报文段在超时规定的时间内是否收到确认,从而来判断该报文段是否丢失或传输出错。TCP使用了4种计时器:重传计时器、坚持计时器、保持计时器和时间等待计时器来保证了传输的可靠性。
      TCP协议通过哪些方法保证数据传输的可靠性

      TCP 可靠传输的实现(二)TCP的重传机制

      TCP使用可靠的传输协议,即意味着必须按序、无差错的传送数据到目的端,那么如果在传输过程中发送的包丢失了该怎么办?TCP的重传机制就是:如果发送方认为发生了丢包现象就重发这些数据包。显然,我们需要一个方法去 猜测是否发生了丢包 。最简单的想法就是,接收方每接收到一个包就向发送者返回一个ACK,表示自己已经收到了这段数据,反过来,如果发送方一段时间内没有收到ACK,就知道 很可能是数据包丢失 了,紧接着就重发该数据包,直到收到ACK为止。 为什么是 猜测 呢? 因为即使是超时了,这个数据包也可能并没有丢,它只是绕了段远程,来的很晚而已。毕竟TCP协议是位于传输层的协议,不可能明确知道数据链路层和物理层发生了什么。但是这并不妨碍我们的超时重传机制,因为接收方会自动忽略收到的重复的包。下面我们具体讲一讲TCP的重传机制:这种机制下,每个数据包都有相应的计时器,当超过指定的时间后,没有收到对方的 ACK 确认应答报文就会重发该数据包。超时时间应该设置为多少我们先来了解一下RTT (Round-Trip Time 往返时延)而超时时间是以RTO(Retransmission Timeout 超时重传时间) 表示。超时时间不宜设置的过长或过短,否则:综上可知,RTO设置的值应该略大于RTT的值。RTO值的计算:https://blog.csdn.net/JXH_123/article/details/27345151值得注意的是:每触发一次超时重传,都 会将下一次超时时间间隔设为先前值的两倍 。遇到超时说明网络环境差,不宜频繁发送。Wireshark 抓包显示:超时重传存在的问题是:当一个报文段丢失时,会等待一定的超时时间后才重传,增加了端到端的时延;当一个报文段丢失时,在其等待超时的过程中,可能会出现这种情况: 其后的报文段已经被接收端接收但却迟迟得不到确认,发送端就也以为丢失了,从而引起不必要的重传,既浪费时间也浪费资源。(例如: 数据包5丢失,数据包6、7、8、9都已到达接收方,这个时候客户端只能等服务端发送ACK,因此对于客户端来说,它完全不知道丢了几个包,可能就悲观的认为:5后面的数据包都丢了,就重传这5个数据包,这就比较浪费了)。刚刚提到过,基于计时器的重传往往要等待很长时间,而快速重传使用了很巧妙的方法来解决这个问题。快速重传(Fast Retransmit)机制 不以时间为驱动,而是以数据为驱动重传。由于TCP采用的是累计确认机制,当接收端收到比期望序号大的报文段时,便会重复发送最近一次确认的报文段的确认号,即冗余 ACK (Duplicate ACK)。这样,如果在超时重传定时器溢出之前,接收到连续的三个重复冗余 ACK (第一个ACK是正常的,后三个是冗余的),发送端便知晓哪个报文段在传输过程中丢失了,于是重发该报文段,而不需要等待超时重传定时器溢出,大大提高了效率。Wireshark 抓包显示:但是,快速重传仍然没有解决第二个问题:到底该重传多少个包?改进的方法就是 SACK (Selective Acknowledgment),简单来说就是在快速重传的基础上,返回最近收到的报文段的序列号范围,这样客户端就知道,哪些数据包已经到达服务器了。看下例子:存在 SACK 选项时当500-599报文到达,接收方发送  ACK 200  ,SACK [500,600)当600-699报文到达,接收方发送  ACK 200  ,SACK [500,700)当700-799报文到达当800-899报文到达当900-999报文到达,接收方累积确认发送  ACK 200  ,SACK [500,1000)连续收到3个重复ACK,发送方经检查发现200-499的数据丢失了,执行快速重传,待接收方接收到200-499的数据,并返回 ACK 1000时,发送方的所有数据均已确认完毕,移动滑动窗口到1000位置处。使用 SACK可以告知发送方 收到了哪些数据,发送方收到这些消息后就会知道哪些数据丢失,然后立即重传丢失的部分。需要注意的是: 只有收到失序的分组时才可能会发送SACK 。SACK 包括了两个TCP选项,一个选项用于标识是否支持 SACK(SACK_Permitted),在TCP建立连接时发送;另一种选项则包含了具体的 SACK信息。(1)SACK_Permitted 选项该选项只允许在TCP连接建立时,有 SYN标志的包中设置,在连接建立阶段,主动发起连接的一方在它的SYN中指定选项。只有在它从另一方的SYN中收到了这个选项之后,SACK机制才会被使能。(2)SACK 信息选项SACK 选项参数告诉对方 已经接收到 并缓存的不连续的数据块,发送方可据此信息检查究竟是哪个块丢失,从而发送相应的数据块。Left Edge:本区块的第一个序号。 Right Edge:本区块的最后序号的下一个序号。[Left Edge, Right Edge)区间的ACK 序号表示本次确认收到的序号。问题1:SACK选项最多能包含多少个需重传的块?由于TCP首部的最大长度为 60 byte,而固定首部占用了 20 byte,对于SACK选项本身占用了2 byte,所以剩下 60-20-2=38 byte。而每个块(包括开始和结束)占用 8 byte,所以最多可标识的块数为 38/8 = 4块,所以 SACK 最多可以包括4个需重传的块。同时由于SACK有些时候会和时间戳(占10字节)一起用,因此,此种情况下最多只有3个SACK。问题2:SACK选项的使用规则是怎么样的?SACK 的发送方,即 报文的接收端第一个块需要指出是哪一个到达的报文触发的 SACK尽可能多的把所有的块填满SACK 要报告最近接收的不连续的数据块SACK 的接收端,即 报文的发送端:数据没有被确认前,都会保持在滑动窗口内每个数据包都有一个 SACKed 的标志,对于已经标示的报文,再次接收到时会忽略如果SACK丢失,超时重传之后,重置所有数据包SACKed 标志DSACK是在SACK的基础上做了一些 扩展 ,主要用于对收到的 重复报文 进行了处理。它的主要作用是:告诉发送方有哪些数据被重复接收了。DSACK同样使用了与SACK一样的报文格式,唯一区别在于: 第一个连续的block指定的是触发DSACK的重复报文的序号空间。如果第一个段的范围被ACK范围所覆盖,那么就是DSACK。或者,第一个段的范围被SACK的第二个段覆盖,那么就是DSACK。引入DSACK的好处有:1)可以让发送方知道,是发出去的包丢了,还是回来的ACK包丢了;2)是不是自己的 timeout 设置太小了,导致重传;3)网络上出现了先发的包后到的情况(又称数据包失序);4)网络上是不是把我的数据包给复制了;总之,DSACK的目的是帮助发送方判断,是否发生了包失序、ACK丢失、包重复或伪重传,让TCP可以更好的做网络流量控制。 超时重传机制能解决数据包丢失的问题,但是超时重传机制存在等待时间太长,浪费时间在等待上,降低了传输效率和无法知道需要重传哪些数据包的问题。 快速重传能解决超时重传的等待时间太长的问题,但是对于究竟该重传哪些包的问题仍然不能有效解决。SACK能需要重传哪些数据包的问题,它可以知道哪些包是被确认接收的,客户端能据此判断需要重传的包。DSACK则是作为SACK的一个辅助措施,可以用来判断网络究竟是出现了什么情况,据此做好网络流量控制。
      TCP 可靠传输的实现(二)TCP的重传机制

      TCP协议如何保证可靠传输

      所以 TCP 针对数据包丢失的情况,会用重传机制解决。重传机制的其中一个方式,就是在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的 ACK 确认应答报文,就会重发该数据,也就是我们常说的超时重传。TCP 会在以下两种情况发生超时重传:我们先来了解一下什么是 RTT(Round-Trip Time 往返时延),从下图我们就可以知道:RTT 指的是数据发送时刻到接收到确认的时刻的差值,也就是包的往返时间。上图中有两种超时时间不同的情况:精确的测量超时时间 RTO 的值是非常重要的,这可让我们的重传机制更高效。根据上述的两种情况,我们可以得知,超时重传时间 RTO 的值应该略大于报文往返 RTT 的值。如果超时重发的数据,再次超时的时候,又需要重传的时候,TCP 的策略是超时间隔加倍。也就是每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送。超时触发重传存在的问题是,超时周期可能相对较长。那是不是可以有更快的方式呢?于是就可以用「快速重传」机制来解决超时重发的时间等待。TCP 还有另外一种快速重传(Fast Retransmit)机制,它不以时间为驱动,而是以数据驱动重传。快速重传机制,是如何工作的呢?其实很简单,一图胜千言。在上图,发送方发出了 1,2,3,4,5 份数据:还有一种实现重传机制的方式叫:SACK( Selective Acknowledgment 选择性确认)。这种方式需要在 TCP 头部「选项」字段里加一个 SACK 的东西,它可以将缓存的地图发送给发送方,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。如下图,发送方收到了三次同样的 ACK 确认报文,于是就会触发快速重发机制,通过 SACK 信息发现只有 200~299 这段数据丢失,则重发时,就只选择了这个 TCP 段进行重复。Duplicate SACK 又称 D-SACK,其主要使用了 SACK 来告诉「发送方」有哪些数据被重复接收了。下面举例两个栗子,来说明 D-SACK 的作用。这个模式就有点像我和你面对面聊天,你一句我一句。但这种方式的缺点是效率比较低的。如果你说完一句话,我在处理其他事情,没有及时回复你,那你不是要干等着我做完其他事情后,我回复你,你才能说下一句话,很显然这不现实。所以,这样的传输方式有一个缺点:数据包的往返时间越长,通信的效率就越低。为解决这个问题,TCP 引入了窗口这个概念。即使在往返时间较长的情况下,它也不会降低网络通信的效率。那么有了窗口,就可以指定窗口大小,窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值。窗口的实现实际上是操作系统开辟的一个缓存空间,发送方主机在等到确认应答返回之前,必须在缓冲区中保留已发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。假设窗口大小为 3 个 TCP 段,那么发送方就可以「连续发送」 3 个 TCP 段,并且中途若有 ACK 丢失,可以通过「下一个确认应答进行确认」。TCP 头里有一个字段叫 Window,也就是窗口大小。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。所以,通常窗口的大小是由接收方的窗口大小来决定的。发送方发送的数据大小不能超过接收方的窗口大小,否则接收方就无法正常接收到数据。并不是完全相等,接收窗口的大小是约等于发送窗口的大小的。因为滑动窗口并不是一成不变的。比如,当接收方的应用进程读取数据的速度非常快的话,这样的话接收窗口可以很快的就空缺出来。那么新的接收窗口大小,是通过 TCP 报文中的 Windows 字段来告诉发送方。那么这个传输过程是存在时延的,所以接收窗口和发送窗口是约等于的关系。如果一直无脑的发数据给对方,但对方处理不过来,那么就会导致触发重发机制,从而导致网络流量的无端的浪费。为了解决这种现象发生,TCP 提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制。前面的流量控制例子,我们假定了发送窗口和接收窗口是不变的,但是实际上,发送窗口和接收窗口中所存放的字节数,都是放在操作系统内存缓冲区中的,而操作系统的缓冲区,会被操作系统调整。可见最后窗口都收缩为 0 了,也就是发生了窗口关闭。当发送方可用窗口变为 0 时,发送方实际上会定时发送窗口探测报文,以便知道接收方的窗口是否发生了改变,这个内容后面会说,这里先简单提一下。所以,如果发生了先减少缓存,再收缩窗口,就会出现丢包的现象。为了防止这种情况发生,TCP 规定是不允许同时减少缓存又收缩窗口的,而是采用先收缩窗口,过段时间再减少缓存,这样就可以避免了丢包情况。在前面我们都看到了,TCP 通过让接收方指明希望从发送方接收的数据大小(窗口大小)来进行流量控制。这会导致发送方一直等待接收方的非 0 窗口通知,接收方也一直等待发送方的数据,如不采取措施,这种相互等待的过程,会造成了死锁的现象。窗口探测的次数一般为 3 次,每次大约 30-60 秒(不同的实现可能会不一样)。如果 3 次过后接收窗口还是 0 的话,有的 TCP 实现就会发RST报文来中断连接。一般来说,计算机网络都处在一个共享的环境。因此也有可能会因为其他主机之间的通信使得网络拥堵。在网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是一重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环被不断地放大....所以,TCP 不能忽略网络上发生的事,它被设计成一个无私的协议,当网络发送拥塞时,TCP 会自我牺牲,降低发送的数据量。于是,就有了拥塞控制,控制的目的就是避免「发送方」的数据填满整个网络。为了在「发送方」调节所要发送数据的量,定义了一个叫做「拥塞窗口」的概念。拥塞控制主要是四个算法:TCP 在刚建立连接完成后,首先是有个慢启动的过程,这个慢启动的意思就是一点一点的提高发送数据包的数量,如果一上来就发大量的数据,这不是给网络添堵吗?慢启动的算法记住一个规则就行:当发送方每收到一个 ACK,拥塞窗口 cwnd 的大小就会加 1。这里假定拥塞窗口 cwnd 和发送窗口 swnd 相等,下面举个栗子:连接建立完成后,一开始初始化 cwnd = 1,表示可以传一个 MSS 大小的数据。当收到一个 ACK 确认应答后,cwnd 增加 1,于是一次能够发送 2 个当收到 2 个的 ACK 确认应答后, cwnd 增加 2,于是就可以比之前多发2 个,所以这一次能够发送 4 个当这 4 个的 ACK 确认到来的时候,每个确认 cwnd 增加 1, 4 个确认 cwnd 增加 4,于是就可以比之前多发 4 个,所以这一次能够发送 8 个。可以看出慢启动算法,发包的个数是指数性的增长。有一个叫慢启动门限ssthresh(slow start threshold)状态变量。前面说道,当拥塞窗口 cwnd 「超过」慢启动门限 ssthresh 就会进入拥塞避免算法。一般来说 ssthresh 的大小是 65535 字节。那么进入拥塞避免算法后,它的规则是:每当收到一个 ACK 时,cwnd 增加 1/cwnd。接上前面的慢启动的栗子,现假定 ssthresh 为 8:当 8 个 ACK 应答确认到来时,每个确认增加 1/8,8 个 ACK 确认 cwnd 一共增加 1,于是这一次能够发送 9 个 MSS 大小的数据,变成了线性增长。所以,我们可以发现,拥塞避免算法就是将原本慢启动算法的指数增长变成了线性增长,还是增长阶段,但是增长速度缓慢了一些。就这么一直增长着后,网络就会慢慢进入了拥塞的状况了,于是就会出现丢包现象,这时就需要对丢失的数据包进行重传。当触发了重传机制,也就进入了「拥塞发生算法」。当网络出现拥塞,也就是会发生数据包重传,重传机制主要有两种:发生超时重传的拥塞发生算法当发生了「超时重传」,则就会使用拥塞发生算法。这个时候,ssthresh 和 cwnd 的值会发生变化:还有更好的方式,前面我们讲过「快速重传算法」。当接收方发现丢了一个中间包的时候,发送三次前一个包的 ACK,于是发送端就会快速地重传,不必等待超时再重传。TCP 认为这种情况不严重,因为大部分没丢,只丢了一小部分,则ssthresh和cwnd变化如下:快速重传和快速恢复算法一般同时使用,快速恢复算法是认为,你还能收到 3 个重复 ACK 说明网络也不那么糟糕,所以没有必要像 RTO 超时那么强烈。正如前面所说,进入快速恢复之前,cwnd 和 ssthresh 已被更新了:
      TCP协议如何保证可靠传输

      tcp协议实现可靠传输的原理是什么

      TCP/IP协议 TCP/IP(Transmission Control Protocol/Internet Protocol的简写,中文译名为传输控制协议/互联网络协议)协议是Internet最基本的协议,简单地说,就是由网络层的IP协议和传输层的TCP协议组成的。 通俗而言:TCP负责发现传输的问题,一有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地。而IP是给因特网的每一台电脑规定一个地址。1974年12月,卡恩、瑟夫的第一份TCP协议详细说明正式发表。当时美国国防部与三个科学家小组签定了完成TCP/IP的协议,结果由瑟夫领衔的小组捷足先登,首先制定出了通过详细定义的TCP/IP协议标准。当时作了一个试验,将信息包通过点对点的卫星网络,再通过陆地电缆,再通过卫星网络,再由地面传输,贯串欧洲和美国,经过各种电脑系统,全程9.4万公里竟然没有丢失一个数据位,远距离的可靠数据传输证明了TCP/IP协议的成功。
      tcp协议实现可靠传输的原理是什么

      本文由 在线网速测试 整理编辑,转载请注明出处。

          热门文章

          文章分类