面试的时候,经常会问到网络通信这块,尤其是让详细讲讲三次握手与四次挥手,很多时候我们能讲个大概,但是面试官总是不满意。
TCP
扮演着重要的角色,它位于传输层,负责确保数据的可靠性和有序性。通信的开始和结束都需要经历连接的建立和断开过程,下面我们详细讨论下TCP
的三次握手 和四次挥手机制,是如何实现这一过程的,也希望对你有所帮助。
三次握手和四次挥手
讲个小故事,让我们快速理解下
三次握手和四次挥手过程其实也是建立连接 和断开连接 的过程,我们可以通过一个小故事来形象化地简述一下:(小明和小芳的爱情史...)
小明打算追求小芳...
三次握手(建立关系):
- 小明主动追求 :"小芳,我一直觉得你很特别,我们能不能试着在一起?"(
SYN
包) 小芳心动回应
:"嗯,我也有同样的感觉,我们试试看吧"(SYN+ACK
包)- 小明开心确认 :"你同意了,太好了!"(
ACK
包)
开始聊天、发送消息,一段时间后...
四次挥手(结束关系):
- 小明想结束这段关系,提出分手 :"我觉得我们之间不如以前了,或许我们结束比较好"(发送
FIN
包) 小芳表示理解
:"好吧,我理解,但有些事情我还想和你说说"(回复ACK
包)小芳也提出分手
:"或许你说得对,我们结束吧,希望你未来能够找到更适合你的幸福"(再次发送FIN
包)- 小明接到分手消息 :"好吧,我知道了。但我后悔了,能给我们一个重新开始的机会吗?"(再次发送
ACK
包)
小明事后后悔了,希望可以重新开始。小芳表示可以,但是必须重新追求...
TCP
每次握手和挥手,都是建立关系和结束关系的过程,我们先来说说在建立关系和结束关系的过程,常见的标志位、序列号和确认号。
标志位、序列号和确认号
当涉及到TCP连接的建立和断开时,请求报文(传递数据)是关键的一环。以下是一个综合的描述,包含了标志位、序列号、确认号的简要介绍:
1、标志位:
- SYN(同步): 发送方使用SYN标志发起新连接。
- ACK(确认): 表示确认号字段有效,用于确认接收到的数据。
- FIN(结束): 发送方发送,表示请求关闭连接,在数据传输完成后使用。
2、序列号(seq):
- 用于标识TCP数据流中每个数据段的顺序。
- 发送方为每个数据段分配唯一序列号,接收方通过序列号重新组装数据。
3、确认号(ack):
- 表示期望下一次接收的数据包序列号。
- 接收方通过发送带有确认号的ACK数据包,通知发送方哪些数据已成功接收。
综合这些概念,TCP连接的建立通常以发送SYN标志的请求报文开始。接收方通过发送带有SYN和ACK标志的响应报文进行确认。序列号和确认号的正确使用确保了数据的有序传输和可靠接收。断开连接时,FIN标志的使用表明发送方请求关闭连接,而接收方通过发送带有确认号的ACK响应来确认关闭请求。
下面让我们继续看看具体的实现过程,其中
ACK=1
表示确认,SYN=1
表示同步,FIN=1
表示关闭。
TCP三次握手: 建立连接
-
第一次握手(SYN):建立连接的请求。
- 客户端发送
SYN=1
标志,以及随机生成的初始序列号seq=x
。 - 客户端进程进入 SYN-SENT 状态,等待服务器的确认。
- 客户端发送
-
第二次握手(SYN-ACK):确认连接请求。
- 服务器端接收到请求后,回复带有
SYN=1
和ACK=1
标志,以及确认号ack=x+1
和自己的初始序列号seq=y
。 - 服务器进程进入 SYN-RCVD 状态,等待客户端的最终确认。
- 服务器端接收到请求后,回复带有
-
第三次握手(ACK):连接确认。
- 客户端接收到服务器的响应后,发送带有
ACK=1
标志、确认号ack=y+1
、序列号seq=x+1
的数据包。 - 此时建立连接完成(ESTABLISHED)
- 客户端接收到服务器的响应后,发送带有
TCP四次挥手:断开连接
-
第一次挥手(FIN):发起关闭请求。
- 客户端发送带有
FIN=1
标志和序列号seq=x
的数据包,表示它准备关闭连接。 - 客户端进入 FIN-WAIT-1 状态。
- 客户端发送带有
-
第二次挥手(ACK):确认关闭请求。
- 服务器接收到关闭请求后,发送带有
ACK=1
标志、确认号ack=x+1
和自己的序列号seq=y
的数据包,表示已接收到关闭请求并确认。 - 服务器进入 CLOSE-WAIT 状态。(半关闭状态,即客户端已经没有数据要发送了,但是服务端若发送数据,客户端依然要接受)
- 客户端收到确认后,进入 FIN-WAIT-2 状态,等待服务器发送连接释放报文。在这个状态中,客户端可以接收服务端的最后数据。
- 服务器接收到关闭请求后,发送带有
-
第三次挥手(FIN):发起关闭确认。
- 服务器发送带有
FIN=1
和ACK=1
标志位、确认号ack=x+1
和自己的序列号seq=z
的数据包。 - 服务器进入 LAST-ACK 状态,等待客户端的确认。
- 服务器发送带有
-
第四次挥手(ACK):关闭连接完成。
- 客户端接收到服务器的关闭请求后,发送带有
ACK=1
标志、确认号ack=z+1
和自己的序列号seq=x+1
的数据包。 - 客户端进入 TIME-WAIT 状态,等待 2MSL(最长报文段寿命) 的时间。
- 服务端收到客户端确认报文后,撤销自己的传输控制块TCB,进入 CLOSED 状态。
- 客户端经过 2MSL 的等待后,也撤销相应传输控制块TCB,进入 CLOSED 状态。此时,TCP连接彻底断开。
- 客户端接收到服务器的关闭请求后,发送带有
2MSL 指的是报文段的最长生存时间,通常用来等待在网络中被丢弃或产生的延迟、重复数据包被清除。
TCB 指TCP连接的状态和控制信息,每个TCP连接都有一个对应的TCB。
为什么需要三次握手和四次挥手?
保证连接的可靠性和完整性
在网络通信中,保证连接的可靠性和数据的完整性很重要。通过三次握手,双方可以建立起可靠的连接。而通过四次挥手,双方可以安全地关闭连接,保证数据的完整传输。
处理网络异常和延迟情况
在实际网络环境中,存在各种可能导致通信异常的情况,比如网络延迟、丢包等。三次握手和四次挥手的目的就是为了保持连接的稳定性和可靠性。
- 处理网络延迟:通过三次握手,可以减少因网络延迟而导致的连接建立问题,双方都确认。
- 处理丢包情况:在网络通信中,数据包可能会因为各种原因丢失。通过四次挥手过程,可以保证数据完整,这其中序列号起了很大作用。
- 处理半开连接问题:如果没有四次挥手过程,可能会导致半开连接的情况,即一方已经关闭连接,但另一方仍然在发送数据。
- 处理连接复用问题:在一些场景下,需要复用已经建立的连接来提高效率。四次挥手可以避免这一类的问题发生。
总结
综合来说,三次握手和四次挥手的过程是TCP通信的基础。更是保证了连接的稳定性和数据的完整传输,同时也能够处理各种网络异常情况,提升通信的可靠性和稳定性。