深入理解TCP连接:三次握手和四次挥手
在网络通信中,TCP(传输控制协议)扮演着重要的角色。TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,它在发送数据前,通信双方必须在彼此间建立一条连接。本文将深入探讨TCP连接的建立和断开过程,着重关注三次握手和四次挥手的原理和过程。
1. TCP报文的头部结构
在了解TCP连接之前,先来了解一下TCP报文的头部结构。TCP报文头部包含了多个字段,其中包括序号、确认序号、标志位等。这些字段在TCP连接的建立和断开过程中起着重要作用。
- 序号(Seq Number):占32位,用于标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
- 确认序号(Ack Number):占32位,只有ACK标志位为1时,确认序号字段才有效。确认序号通常等于对方发送的序号加一,表示已经成功接收到了这个序号之前的所有数据。
- 标志位:共6个,包括:
- ACK:确认序号有效。
- FIN:释放一个连接。
- PSH:接收方应该尽快将这个报文交给应用层。
- RST:重置连接。
- SYN:发起一个新连接。
- URG:紧急指针(urgent pointer)有效。
2. 三次握手的原理与过程
三次握手的本质是确认通信双方收发数据的能力首先,我让信使运输一份信件给对方,对方收到了,那么他就知道了我的发件能力和他的收件能力是可以的。一个TCP连接由一个4元组构成,分别是两个IP地址和两个端口号。TCP连接通常分为三个阶段:连接、数据传输、退出(关闭)。连接阶段通过三次握手建立,退出阶段通过四次挥手来关闭。
三次握手
举个栗子先吧
想象一下,有两位朋友,小明和小红,他们之间需要通过写信来进行交流。这个过程就像是建立TCP连接的三次握手。
-
第一次握手:小明发出邀请
小明向小红写了一封信,表达了与她建立联系的意愿,并附上了自己的联系方式。这相当于客户端向服务器发送连接请求报文,带有一个序列号和请求信息,并携带了SYN 标志。
-
第二次握手:小红确认邀
小红收到了小明的信后,理解了他想要与她通信的意图,并写了回信给小明,确认了自己的联系方式,并附上了自己的联系方式。这封回信相当于服务器对客户端的回应,其中包含了确认信息和服务器的序列号,并带有SYN 和 ACK 标志。
-
第三次握手:小明回复确认
小明收到了小红的回信后,确认了小红的联系方式,并回复了一封信给小红,表明自己已经收到了小红的回信,并准备好开始正式的通信。这封回复信相当于客户端对服务器的确认,其中包含了确认信息,并带有 ACK 标志。
通过这样的三次交流,小明和小红建立了可靠的通信连接,并可以开始进行进一步的交流。
连接建立过程解析
在TCP连接建立的过程中,这三次握手实际上包含了以下步骤:
-
第一次握手:客户端发送连接请求
客户端向服务器发送一个带有SYN 标志的连接请求报文,其中包含了一个随机生成的序列号。
-
第二次握手:服务器确认连接请求
服务器收到连接请求后,发送一个带有SYN和ACK 标志的确认报文,其中包含了确认号(客户端序列号+1)和服务器自己的随机生成的序列号。
-
第三次握手:客户端确认连接
客户端收到服务器的确认后,发送一个带有ACK 标志的确认报文,其中包含了确认号(服务器序列号+1)。
通过这三次握手,客户端和服务器建立了可靠的通信连接,可以开始进行数据传输。
3. 四次挥手的原理与过程
在TCP(Transmission Control Protocol)连接中,四次挥手是用于关闭连接的过程。尽管这个过程相对于三次握手来说更为复杂,但通过详细的解析,我们可以更好地理解其中的每个步骤和顺序。
四次挥手
为了更好地理解TCP四次挥手的过程,我们可以用一个简单的比喻来解释:
想象一下,有两位朋友,小明和小红,他们之间通过书信往来进行交流。这个过程就像是TCP连接的四次挥手。
-
第一次挥手:小明发出告别
当小明觉得与小红的交流结束时,他首先向小红发送一封告别信,表明自己不再需要继续通信。这封信中包含了一个FIN 标志位,表示告知对方已经不会再发送数据了,以及一个序列号,表示最后一个已发送的数据的序列号。
-
第二次挥手:小红确认告别
小红收到了小明的告别信后,确认了小明不再需要继续通信,并向小明回复了一封确认信,表示自己已经知道了小明的意图。这封确认信中包含了一个ACK 标志位和一个确认号,确认了小明的序列号,并且也包含了小红自己的序列号。
-
第三次挥手:小红告别
小红在确认了小明的告别后,也觉得不再需要继续通信,于是她向小明发送了一封告别信,表示自己不会再发送数据了。这封信中包含了一个FIN 标志位和一个序列号,表示告知小明自己不会再发送数据了。
-
第四次挥手:小明确认告别
小明收到小红的告别信后,确认了小红的意图,并向小红回复了一封确认信,表示自己已经知道了小红不再发送数据的意图。这封确认信中包含了一个ACK 标志位和一个确认号,确认了小红的序列号,并且表示自己不会再发送数据了。
通过这四次挥手,小明和小红完成了通信的结束,彼此知道对方不再发送数据,并且关闭了连接。
连接关闭过程的解析
接下来,我们来详细分析每个步骤中的具体内容和顺序:
-
第一次挥手:客户端发送连接释放报文
客户端在确定不再发送数据后,向服务器发送一个带有FIN 标志的连接释放报文,其中包含了一个序列号,表示客户端最后一个已发送的数据的序列号。
-
第二次挥手:服务器确认连接释放报文
服务器收到客户端发送的连接释放报文后,回复一个带有ACK 和确认号的确认报文,表示已经收到了客户端的连接释放请求,并且确认了客户端的序列号。
-
第三次挥手:服务器发送连接释放报文
服务器在确定不再发送数据后,向客户端发送一个带有FIN 标志的连接释放报文,其中包含了一个序列号,表示服务器最后一个已发送的数据的序列号。
-
第四次挥手:客户端确认连接释放报文
客户端收到服务器发送的连接释放报文后,回复一个带有ACK 和确认号的确认报文,表示已经收到了服务器的连接释放请求,并且确认了服务器的序列号。
通过这四次挥手,客户端和服务器完成了连接的关闭,彼此确认不再发送数据,并且释放了连接资源。
4. 常见面试题
为什么TCP连接的时候是3次?2次不可以吗?
- 因为需要考虑连接时丢包的问题,如果只握手2次,第二次握手时如果服务端发给客户端的确认报文段丢失,此时服务端已经准备好了收发数(可以理解服务端已经连接成功)据,而客户端一直没收到服务端的确认报文,所以客户端就不知道服务端是否已经准备好了(可以理解为客户端未连接成功),这种情况下客户端不会给服务端发数据,也会忽略服务端发过来的数据。如果是三次握手,即便发生丢包也不会有问题,比如如果第三次握手客户端发的确认ack报文丢失,服务端在一段时间内没有收到确认ack报文的话就会重新进行第二次握手,也就是服务端会重发SYN报文段,客户端收到重发的报文段后会再次给服务端发送确认ack报文。
为什么TCP连接的时候是3次,关闭的时候却是4次?
- 因为只有在客户端和服务端都没有数据要发送的时候才能断开TCP。而客户端发出FIN报文时只能保证客户端没有数据发了,服务端还有没有数据发客户端是不知道的。而服务端收到客户端的FIN报文后只能先回复客户端一个确认报文来告诉客户端我服务端已经收到你的FIN报文了,但我服务端还有一些数据没发完,等这些数据发完了服务端才能给客户端发FIN报文(所以不能一次性将确认报文和FIN报文发给客户端,就是这里多出来了一次)。
为什么客户端发出第四次挥手的确认报文后要等2MSL的时间才能释放TCP连接?
- 这里同样是要考虑丢包的问题,如果第四次挥手的报文丢失,服务端没收到确认ack报文就会重发第三次挥手的报文,这样报文一去一回最长时间就是2MSL,所以需要等这么长时间来确认服务端确实已经收到了。