【计算机网络】TCP协议技术细节全解析:与UDP的核心差异深度对比
目录
引言
TCP的四大计时器
1)重传计时器
2)持续计时器
3)保活计时器
4)时间等待计时器
为什么一定要进行三次握手?两次不行吗?
流量控制和拥塞控制有什么区别?
TCP和UDP的区别
为什么UDP有时比TCP更有优势?
为什么会有TIME_WAIT状态?该状态持续多长时间?为什么?
引言
这篇博客实际上是对上一篇【计算机网络】一文读懂TCP:从三次握手到拥塞控制的全面指南-CSDN博客 的补充,由于篇幅原因,好多关键的细节问题并没有在上一篇博客中体现,而是放到了这里。如果想对TCP的全过程有个细致的了解,可以点击上面链接进行学习。本篇博客呢就是以问题导向为主,专注于去解答面试中常见的细节问题。
TCP的四大计时器
1)重传计时器
在一个TCP连接中,TCP每发送一个报文段,就会对此报文段设置一个超时重传计时器,如果超时重传计时器已经到期,但还未收到接收方的确认,那么发送方就会重发该报文段,并将重传计时器复位。
2)持续计时器
首先我们谈谈持续计时器出现的背景,就是说,它的出现是为了解决什么问题的。为了打破TCP中的一种死锁局面。
假设A为发送方,B为接收方。当A在收到B的零窗口报文后,就不能再向B继续发送数据了。而是要等待B发来确认,告诉A可以发送数据了(非零窗口报文),A在收到这个确认报文后才可以继续向B发送数据。但是我们知道,B发出的这个非零窗口报文(本质就是个确认报文)可能会丢失。我们知道,对确认是不需要发送确认的,否则会导致无限循环下去。所以呢,B就以为A收到了这个确认报文。然后B就在等A发来数据,A在等B发来的窗口更新报文。就这样僵持下去,互相等待,导致死锁。持续计时器的出现就是为了打破这样的僵局。
当A收到一个窗口大小为0的确认时,就会启动持续计时器。当持续计时器到期后,A会向B发送探测报文询问窗口的情况。即使B发送给A的窗口更新丢了,也不会导致死锁。持续计时器可以防止因窗口更新丢失而导致的死锁。
3)保活计时器
保活计时器是一种用于检测空闲连接是否有效的机制。有这样一种场景,客户端与服务器建立了TCP连接,后来客户端的主机突然出现故障。显然,以后服务器就不能再收到客户端发来的数据了。因此,应当有措施使服务器不要在白白等下去。这时,保活计时器就派上用场了。如果客户端和服务器在2个小时内没有数据交互,那么就会触发保活计时器。服务器就会向客户端发送一个探测报文,如果服务器收到了对方的ACK,说明对方正常,然后重置保活计时器,保持空闲。如果服务器没有收到对方的ACK,那么接下来每隔75秒发送一次探测报文,若一连发送10个探测报文段后仍无客户响应,服务器就认为客户端出现了故障,接着就关闭这个连接。
4)时间等待计时器
时间等待计时器与四次挥手过程的最终阶段密切相关。它是TCP终止连接机制中的重要组成部分,用于确保连接的可靠关闭。当主动关闭的一方发送最终的ACK确认对方的FIN时,主动关闭的一方就会进入TIME_WAIT状态,它的等待时长默认是:2*MSL(Maximum Segment Lifetime,报文段最大生存时间)。它的第一个作用是:处理最终ACK丢失的容错。如果被动关闭的一方迟迟收不到最终的ACK,那么会重传FIN报文,此时主动关闭的一方处于TIME_WAIT状态,就可以对收到的FIN进行应答。确保被动关闭方能正确关闭连接,避免其陷入LAST-ACK状态无法终结。第二个作用就是防止旧连接报文干扰新连接。若立即释放连接并复用相同四元组(源IP、源端口、目的IP、目的端口),网络中延迟的旧报文可能被新连接误接收。等待2*MSL
确保网络中所有旧连接的报文过期(超过MSL的报文将被丢弃),杜绝数据串扰。
为什么一定要进行三次握手?两次不行吗?
当客户端向服务器发送一个连接请求报文时,由于某种原因,导致这个连接请求报文长时间驻留在某个网络节点中,无法到达服务器。客户端由于超时计时器到期仍没有收到服务器的确认,会重新向服务器发送连接请求报文,而且该连接请求得到了服务器端的响应并正常建立连接,进而传输数据,但数据传输完毕后,就释放了此次的TCP连接。若此时第一次发送的连接请求报文延迟一段时间后,到达了服务器。本来这是一个早已失效的报文段的,但是服务器却误以为客户端又发出了一次新的连接请求,于是,服务器向客户端发出确认应答,并同意建立连接。如果采用的是两次握手,那么服务器就认为连接已经成功建立。但是实际上,客户端并没有向服务器发送任何请求,所以客户端就忽略服务器的确认应答,更不会向服务器发送任何数据。这样,服务器就一直处于等待接收数据的状态,直到超出计数器的设定值,才会关闭连接。在等待的过程中,就浪费了服务器的资源。但是,如果采用的是三次握手,服务器会因为没有收到客户端的确认应答,而判定客户端并没有想要建立连接,从而不建立该连接。
关于为什么一定要三次握手,我这里给出另一种回答。
客户端向服务器发送连接请求报文SYN,服务器收到后,同意建立连接,并向客户端发送确认(SYN+ACK),当客户端收到服务器的确认后,证明客户端的发送(SYN)和接收(SYN+ACK)功能是正常的。接着,客户端向服务器发送确认。当服务器收到该确认后,就成功建立了连接。服务器收到对SYN+ACK报文的确认以后,也可以证明它的发送能力和接收能力是正常的。合起来,就是双方的发送和接收能力均正常。通过这样,建立的连接才是可靠的。
流量控制和拥塞控制有什么区别?
1)作用对象不同。流量控制是端到端的问题,它针对的是接收方的处理能力。而拥塞控制是全局性的,它关注整个网络的状况。
2)触发因素不同。流量控制是由接收方的缓冲区决定的,而拥塞控制是由网络中丢包导致超时重传等因素触发的。
3)实现机制不同。流量控制主要是通过滑动窗口来实现的,而拥塞控制则是由拥塞窗口以及多种算法来共同实现的。
4)目标不同。流量控制是保护接收方,而拥塞控制是保护网络。
TCP和UDP的区别
1)TCP面向连接,UDP无连接。
2)TCP提供可靠服务,也就是说,通过TCP连接传送数据,无差错、不丢失、不重复而且按序到达;UDP尽最大努力交付。
3)每一条TCP连接只能是点到点的;UDP支持一对一、一对多、多对一、多对多的交互通信。
4)TCP对系统资源要求较高,内存占用大而且计算开销高。所谓对系统资源要求高,就是需要维护很多变量,比如序列号、窗口大小、确认号、重传队列等等。每个连接都需要维护这些数据结构,所以当并发连接数很高的时候,内存消耗自然增加。所谓的计算开销高,TCP的重传机制、拥塞控制、流量控制都需要复杂的计算。比如每收到一个ACK,需要更新窗口,检查是否有数据需要重传,这些都会消耗CPU资源。UDP对系统资源就比较少。
5)TCP面向字节流,UDP面向数据报。
为什么UDP有时比TCP更有优势?
1)UDP极低的延迟与开销。
① UDP面向无连接,直接发送数据报,适合实时性要求极高的场景。
② UDP没有拥塞控制,TCP的拥塞控制机制会动态调整发送速率,而UDP直接以最高速率发送数据,适合需要抢占带宽的应用。
③ UDP头部开销小,仅有8个字节,而TCP至少20字节,所以UDP的传输效率较高。
2)容忍丢包的场景。
比如在视频/音频传输中,少量丢包可通过前向纠错(FEC)或重传关键帧恢复,而TCP的重传机制会导致延迟累积。
3)UDP的简单性与灵活性。
UDP编程复杂度低,而且可以自定义可靠性,比TCP的全局可靠性要灵活。
4)UDP支持多播/广播。UDP天然支持一对多通信,而TCP需要额外的机制实现。
为什么会有TIME_WAIT状态?该状态持续多长时间?为什么?
1)为了确保TCP连接的可靠释放。
最终的ACK是由主动关闭方发出的,如果这个ACK丢失,被动关闭方将重发最终的FIN,因此主动关闭方必须维持状态信息允许它重发最终的ACK。如果主动关闭方不维持TIME_WAIT状态而是直接进入CLOSED状态,那么主动关闭方在收到被动关闭方重传的FIN时,将响应RST(复位)包,这会导致被动关闭方立即终止连接。这种情况会导致连接异常终止,可能会影响被动关闭方的资源释放。
2)为使旧的数据包在网络中因过期而消失。
若立即释放连接并复用相同四元组(源IP、源端口、目的IP、目的端口),网络中延迟的旧报文可能被新连接误接收。等待2*MSL
确保网络中所有旧连接的报文过期(超过MSL的报文将被丢弃),杜绝数据串扰。
3)TIME_WAIT持续2 * MSL的时间。一个MSL是确保最终ACK有足够的时间到达被动关闭的一方(即使丢失,被动关闭的一方会在MSL内重传FIN)。第二个MSL是为了能够对重传FIN做出正确响应,因为FIN最迟最迟在一个MSL时间内完全可以到达主动关闭方,主动关闭方在重发最终的ACK后重置TIME_WAIT计时器。从主动关闭方到被动关闭方,最长需要MSL,发过来也是,从被动关闭方到主动关闭方,最长需要MSL,加起来2倍的MSL。总的来说,就是确保两个方向的报文均有足够的时间在网络中消亡。