目录
开篇
一、TCP如何保证可靠传输?
1、滑动窗口
2、超时重传和快速重传
3、选择确认
二、TCP的流量控制
三、TCP三次握手
四、TCP四次挥手
五、TCP的拥塞控制
1、慢启动和拥塞避免
2、快速恢复
结语
今天下午广州下着小雨,屋外“沙沙”的雨声很治愈,心情舒畅,想起诗句“小桥流水人家”,已经好久没接触古诗词啦,现在想想以前学的古典文学,有种久违的优美。驾一叶扁舟于江中,朦胧细雨,惠风和畅。以上这句话是我自己编的๑乛◡乛๑,以后有时间就读读古诗文学,感觉挺不错的*^_^*
后来雨下得越来越大,还伴有“轰隆”的雷声,这时我才缓过神来,发现写着写着跑题了哈,然后赶紧进入正题,外面的风景虽好,自己的遐想也好,今天任务还没完成呢!今天想要写的学习总结是TCP非常关键的知识,正如我起的题目“必须掌握的TCP全家桶系列”,后面会发现这一系列下来,联系都挺密切的,感兴趣的伙伴可以往前找我写的,比如《运输层UDP报文、TCP协议内容 一篇精华总结!》。
“滑动窗口”这个概念现在应该不陌生了,在数据链路层的时候就出现过这个概念,是一个很形象的名字,协议的工作过程中,发送窗口不断向前滑动。可以瞧瞧这篇《计算机网络学习:封装成帧、差错检测和可靠传输》。
当然,这里讲的是运输层TCP协议的可靠传输,原理相似,具体有一点差别。
TCP协议是面向字节的,所以滑动窗口也是以字节为单位。同样采用累积确认的方式,对按序接收到的数据进行确认,确认号表示下一个期望收到数据字节的第一个编号。
另外,因为TCP提供了全双工的通信,不需要双方特地发送确认报文,发送数据的时候捎带确认信息,采用了延迟确认的机制,这样提高了TCP的传输效率。
一图胜万字,就是这样。
上图表示窗口大小为400字节,发送的数据不能超过窗口大小,只有发送的数据被确认后,窗口才向前滑动。比如初始化序号为1,第一次发送1-401字节这段数据,然后收到1-201的确认,窗口向前滑动至701因为301-401未收到确认,现在能使用的窗口只有200字节,也就是说最多只能再发送200字节的数据。
还有一个重要的地方,发送窗口只是发送缓存的一部分,在实际TCP应用程序中,缓存空间和序号空间是有限的,这部分缓存类似循环队列的存在可以循环使用。
在数据链路层中也有超时重传的机制,设置的超时阈值相对简单,因为数据链路层的往返时间比较固定。而TCP中的超时重传机制,就显得比较复杂了,TCP工作的环境十分复杂,网络拥塞情况不确定,这对于设定超时阈值时间就很困难。往返时间PTT的计算有着许多算法,比如自适应算法、Karn算法,目的都是尽可能正确的计算报文的往返时间,这样才能保证可靠传输,没有差错。
尽管这样,在实际中如果一个超时时间比较长,这样效率低下,不利于传输数据。因此,快速重传可以更好的保证TCP的可靠传输并提高效率。
快速重传的工作过程在下图可以很直观地看到。
发送方发送了M1-M6报文,期间M3报文丢失,收到M4时候发现序号不对,后面到达的M5-M6都暂且存放于缓存,这时根据快速重传算法规定,对按序到达的最后的数据的序号进行三次重复确认,表示需要重传下一个序号的数据。
这样一来,可以更快的告知发送方需要重传的数据,保证了效率。
上面提到,TCP采用累积确认的方式,同时会将未按序到达的数据接收存放于缓存,但是这部分已经接收的字节数据并未收到确认,会被误认为超时要求发送方重传。显然,这是多余无意义的。
因此,TCP启用了选择确认的功能。这样接收方可以通知发送到已接收的未按序字节块,发送方就不用再次重传这些数据。这与选择重传协议(SR)很类似,不过它是更改为逐一确认方式。
TCP依然使用累计确认,这时一个确认号不够用,所以需要不连续字节块的左右边界来标识,这部分信息存放在TCP首部的可变长选项。
所谓流量控制,就是接收方会根据自身情况来告知发送方自己的缓存容量,避免发送数据太快来不及接收,造成数据丢失或者缓存溢出。
TCP流量控制更像一种速率匹配服务,匹配发送速率和接收速率。流量控制的方法实质是控制发送窗口的大小。接收方会在TCP首部写入对发送方窗口大小的设置要求,由接收方控制发送方的形式。
上图中,接收方进行了三次流量控制。最后一次告知发送方不能发送数据,因为接受缓存满了。这样一来,如果发送方还有数据,怎么办呀?
这时,为了防止这种死锁的状态,发送方会周期性的发送一个窗口探测报文,强制接收方告知接收窗口大小。
TCP建立连接的三次握手过程可以说是很经典的问题。
那为何是三次握手?
TCP是面向连接的协议,建立连接需要解决这三个问题。
- 使双方的任一方知道对方的存在;
- 双方协商好初始化参数(MSS、窗口大小等);
- 对运输实体资源(缓存大小、状态变量等)进行分配。
TCP连接采用C/S架构。过程如图(来源:百度百科)
详细过程:
第一次握手,客户端向服务器发送连接请求报文,标识SYN=1(表示请求报文),seq=x(表示序号),确认客户端的发送能力和服务器是否有接收能力。
第二次握手,服务器接受请求,进行确认,SYN=1,ACK=1(表示确认),确认号ack=x+1,数据序号seq=y,确认客户端的接收能力和服务器是否有发送能力。
第三次握手,客户端响应服务器的接受连接确认,进行确认收到,SYN=0,ACK=1,ack=y+1,seq=x+1,确认各方的接收能力和发送能力。
回头一看,似乎第三个报文客户端的确认有点多余,其实不然。第三个报文的确认,防止了已失效的连接请求报文段突然传送到服务器,造成错误的问题。
为何会如此一说?
假设一种情况,客户端发送的请求报文并未丢失而是延误时间很长,直到这次连接释放后才传到服务器,显然这是已经失效的报文了。但是,服务器会误认为客户端再次请求,然后发送请求的确认,我们知道这时客户端并不会理睬它,因为它没有发送连接请求。后果就是服务器一直等待客户端发送数据,许多资源因此白白浪费。
如果只有两次握手,这个例子很好理解:
朋友:快借我点钱,我的账号是123XXXXXXXX
你:好的, 我转到你的帐号了,收到了吗
朋友再无应答……
这时候,你的内心???钱会不会没了……
总结下来,两次握手所带来的问题:不可靠,还会造成网络资源的浪费。
因此,第三个报文的确认是必要的,三次握手才能保证双方建立正确的连接,可以互相通信。
TCP释放连接,经过了四次挥手的过程,也可以看作两个两次握手。
看图说话(来源:百度百科)
详细过程:
- 客户端进程发送连接释放报文,并且停止发送数据。TCP报文首部,FIN=1(表示终止),seq=u。TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
- 服务器确认连接释放报文报文,ACK=1,ack=u+1,seq=v,此时,服务端就进入了CLOSE-WAIT(被动关闭等待)状态。客户端向服务器的方向就释放了,处于半关闭状态,客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然可以接受。这个状态还要持续CLOSE-WAIT状态的时间。客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2状态,等待服务器发送连接释放报文。
- 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
- 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2MSL的时间后,才进入CLOSED状态。服务器收到了客户端发出的确认,立即进入CLOSED状态。可以看到,服务器结束TCP连接的时间要比客户端早一些。
TCP的拥塞控制和前面的流量控制联系比较密切,流量控制维护一个接收窗口(rwnd)来限制发送窗口的大小,实际上TCP还维持了一个拥塞窗口(cwnd),窗口大小取决于网络拥塞程度。
所以,TCP发送方在发送报文时,不仅要根据接收方的接收能力,还要全局考虑网络的拥塞程度,调整发送窗口大小。满足公式发送窗口大小=Min(rwnd,cwnd).
TCP对网络拥塞的判断依据:超时或者收到三个重复确认。
拥塞控制算法:慢启动、拥塞避免、快速恢复。
TCP定义了一个慢启动门限ssthresh,有以下过程:
- 当cwnd(拥塞窗口)< ssthresh,使用慢启动算法。即每确认一个新报文,cwnd加1。比如初始化cwnd=1,发送第一个报文M0确认后,cwnd=2;接着可以发送M1、M2,确认后cwnd=4,以此类推,为指数增长。
- 当cwnd > ssthresh ,使用拥塞避免算法。即每轮确认才增加一个单位拥塞窗口,呈线性增长。当网络出现拥塞,ssthresh降为原来的一半,拥塞窗口变为1,重新轮回。拥塞避免实际是使网络不容易出现拥塞。
- 当cwnd = ssthresh ,既能使用慢启动算法,也可以使用拥塞避免算法。
因为拥塞的依据包含超时和三个重复确认,其实这两种情况的拥塞程度是不同的,如果突然将拥塞窗口设置为1,可能造成更剧烈的拥塞。
快速恢复则是快速重传的配套算法。
算法的不同之处在于:当收到的是三个重复确认时候,拥塞窗口不再设置为1,而是设置为新的ssthresh值,然后再使用拥塞避免算法,线性增长。
所以,对于不同情况的拥塞,采用不同的算法更好地保证网络质量。
写到这里,外面的雨还是下得很大,但是影响不大。到现在,计算机网络运输层的部分基本学习总结完成了,我觉得这一篇是最重要的,TCP的核心思想都在这里,如果掌握了这部分对于网络的传输基本都能理解,这篇起名为“必须掌握的TCP全家桶系列详细解读”,很明显它就很重要,是干货,建议阅读收藏哦!
与本篇的知识相关的可以查看:计算机网络学习:封装成帧 、差错检测和可靠传输、运输层UDP报文、TCP协议内容 一篇精华总结!
如果觉得不错欢迎“一键三连”哦,点赞收藏关注,评论提问建议,欢迎交流学习!一起加油进步!
我的CSDN博客:https://csdn-czh.blog.csdn.net/article/details/116356740