个人主页:兜里有颗棉花糖
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创
本专栏旨在分享学习网络编程、计算机网络的一点学习心得,欢迎大家在评论区交流讨论💌
TCP协议为了保证数据传输的可靠性,所以发明了几种机制:确认应答、超时重传、连接管理(即三次握手四次挥手)来确保网络通信中进行数据传输的可靠性,本文中我们对连接管理(即三次握手四次挥手)来进行TCP可靠性分析的讲解。
目录
一、三次握手
在TCP协议中,三次握手是用于建立连接
的过程。客户端和服务器通过互相发送特定的控制报文来确认彼此的可达性和同意建立连接。这个过程确保了双方的通信能力,并且在开始数据传输之前建立了可靠的连接。
四次挥手则是用于关闭连接
的过程。当一方决定关闭连接时,它会发送一个关闭连接的请求给另一方。对方确认接收后,双方分别关闭自己的数据传输,并最终确认关闭连接。这个过程确保了双方在结束通信后,释放资源并关闭连接。
在现实生活中,握手一般用于和对方打招呼,然后再开启后面的话题。网络通信中也是如此,我们通过"握手"来发送一个打招呼的数据(用于触发某些特定的场景,这些数据并不包含业务信息)。
然而A和B要想完成建立连接的过程,就需要3次这样打招呼的数据交互。我们来画张图来表示A、B双方3次打招呼的过程,请看下图:
上图中的四次"交互"完毕之后,A和B之间的连接就算是建立好了,注意,重点来了,上图中的交互看起来好像是4次,但实际上只有3次交互(因为中间两次的交互合并在一起了)
。如下图:
中间的两次交互为什么要合并在一起呢,这样做的好处是什么:我们想一下,如果中间的两次交互分开来进行发送的话,那么这两次发送的数据就需要分别来进行封装,这个时候就需要封装两次;但是如果两次交互合并在一起发送的话,此时就只需要封装一次,成本自然是比封装两次低。综上,三次握手本质上是4次数据交互,只不过对中间两次数据交互进行了合并,两次交互合并成一次交互既可以节省了两次封装和分用的过程,也降低了成本,提高了效率
。
三次握手的意义
- 第一点:
投石问路
三次握手也是TCP保证数据传输可靠性的一种方式:TCP要想保证数据传输的可靠性,就需要以网络传输、网络路径畅通为前提,还可以验证每个主机的发送能力和接收能力是否正常,简单来说三次握手的意义就是投石问路
。
- 第二点:
消息协商
TCP通信过程中,有很多信息需要进行协商,协商这个信息是不是属于本次连接的。为什么这么说呢?是因为网络上传输的信息可能是后发先至的,比如说现在有一个信息迟到了,而此时这个信息所属的连接早就关闭了(服务器与客户端已经断开了上一个连接),此时是一个重新建立的连接,这个时候我们就可以通过消息的信号来明显的识别出这个消息是属于上一个连接的,所以直接将这个连接丢掉即可
。
综上三次握手主要有两个主要意义:意义1(投石问路)
:通过投石问路可以验证网络是否发生故障,也可以验证通信双方的发送接受能力是否正常。意义2(消息协商):
通过协商必要的参数来使客户端和服务器使用相同的参数进行消息传输。
二、四次挥手
四次挥手即断开服务器和客户端之间的连接。我们只要连接的概念就是通信双方各自在内存中保有通向双方对端的信息
,如果我们需要断开连接的话,我们就需要及时释放上面内存中的对端信息。
补充:三次挥手一定是客户端主动向服务器发起的请求;但是四次挥手不一定是谁向谁发起的请求,但绝大多数的情况下都是客户端主动向服务器发起请求建立连接的。
下面是四次挥手
经过上述的四个步骤之后,连接就彻底断开不再使用了,通信双方会各自释放内存中存储的对端信息。
四次挥手能不能3次来完成呢
:这是不可以的,这里我们要明确,有些时候四次挥手确实是可以分为三次来完成的,但是有些时候就不能通过三次即必须通过四次来完成断开连接的任务。最主要的一个原因就是FIN的触发时应用程序的代码来进行控制的:通过调用socket.close()或者线程结束就会触发FIN
(对比三次握手中的ACK,ACK(应答报文)并不是通过应用程序的代码来控制的,ACK是通过内核来进行控制的(接收到FIN之后就会立刻返回ACK,是瞬发的)
)。
如果 socket.close() 执行较慢,也就是客户端和服务器在关闭连接时耗费了一定的时间,即客户端发送FIN包后,服务器需要一定时间才能确认并回复ACK包。在这段时间内,服务器可能还有遗留的数据需要发送给客户端,而合并这两个步骤将无法保证服务器的数据顺利发送给客户端。
因此,为了确保数据的正常传输和保证双方的连接状态同步,四次挥手中间的两个步骤不能合并。它们分别代表了客户端和服务器关闭连接的过程,并且保证了数据的完整性和可靠性。
如果服务器始终不进行close会发生什么:
如果服务器始终不进行关闭的话,此时TCP的状态就会处于CLOSE_WAIT状态(如上图,调用close方法之后TCP的状态就转化为LAST_ACK状态)
,此时造成如下情况:
情况1
:对于服务器来说此时的连接虽然没有关闭,但是此连接实际上是没办法使用的。
情况2
:针对socket进行读操作的话,如果数据还没有读完(即缓冲区还有数据),那么数据依然可以正常读到;如果数据已经读完了的话,此时就会读到EOF(对于字节流来说,返回-1;如果是scanner,hashNext就会为false)。
情况3
:针对socket进行写操作的话,此时就会直接触发异常。
其它情况
:比如说代码忘记调用close方法了,对于客户端来说收不到对方的FIN此时就会等待,但是如果直接等不到的话,那么客户端就会单方面放弃连接,释放对端信息资源(当然理想状态下,我们希望客户端和服务器双方都能够释放对端信息资源,但是如果做不到的话,此时是不影响客户端或者服务器单方面释放对端信息资源的)
三、三次握手四次挥手的丢包问题
三次握手四次挥手过程中,如果出现了丢包的情况,此时依然是会触发重传机制的,即尽可能的进行重传,如果重传多次依然没有重传成功的话,此时就会单方面放弃连接的尝试并释放对端的信息资源。
三次握手的丢包问题:
- 第一次握手时,客户端发送SYN数据包到服务器,如果发生丢包则无法建立连接,此时TCP协议就会触发超时重传机制,客户端就会再次发送SYN数据包。
- 第二次握手时,服务器接收到来自客户端超时重传过来的SYN数据包后,会发送SYN-ACK数据包回应给客户端,当然SYN-ACK数据包有可能丢包,此时就会触发超时重传。
如果超时重传多次之后客户端依然没有接收到SYN-ACK数据包,则客户端则任务服务器不可达,并放弃建立连接的尝试
。 - 第三次握手时,客户端接收到来自服务器的SYN-ACK数据包(当然可能是超时重传过来的SYN-ACK数据包)之后,此时客户端就会向服务器发送ACK数据包(表示客户端已成功收到来自服务器的 SYN-ACK 应答,可以建立连接。)。如果服务器没有接收到ACK数据包,此时依然会发生超时重传机制。如果发生了丢包,那么服务器并不知道客户端接收到了 SYN-ACK 应答,因此连接无法建立。
四次挥手过程中的丢包:
- 第一次挥手:客户端向服务器发送FIN数据包,表示要关闭连接。如果发生丢包,则服务器会继续等待客户端发送FIN数据包,如果服务器一直没有接收到FIN数据包的话,TCP协议就会触发超时重传。
- 第二次挥手:服务器接收到FIN数据包之后,就会向客户端发送ACK数据包,如果发生丢包,则会触发超时重传。
- 第三次挥手:如果客户端没有接收到ACK的话,则触发超时重传,如果超时重传多次后依然没有ACK数据包,客户端可能任务服务器已经关闭连接,并释放对端的资源。
第四次挥手
:。极端情况:在四次挥手过程中,如果第四步中 ACK 数据包被丢失,服务器会认为客户端仍然没有确认连接关闭的请求,因此会认为连接没有完全关闭,会继续等待客户端的确认,并尝试不断发送 FIN 数据包,直到达到超时时间为止。如果 FIN 数据包的重传次数达到上限,服务器会认为连接已经关闭,释放资源。
四、总结
我们现在已经知道TCP协议通过确认应答、超时重传、连接管理来进行保证数据传输的可靠性,其中起到决定性作用的是确认应答,连接管理即三次握手四次挥手在一定程度上可以用来检验网络是否可靠,而确认应答可以则保证每次数据传输都是可靠的。
本文到这里就结束了,希望友友们可以支持一下一键三连哈。嗯,就到这里吧,再见啦!!!