三次握手、四次挥手及相对应面试题
三次握手
SYN:同步序列编号(Synchronize Sequence Numbers),表示建立连接
ACK (Acknowledgement),即确认字符,在数据通信中,接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接收无误。
seq和ack号存在于TCP报文段的首部中,seq是序号,ack是确认号,大小均为4字节
第一次,客户端CLOSE状态,服务端LISTEN状态。客户端向服务端发送SYN(同步序列编号)报文,客户端变成SYN_SEND
第二次,服务端收到SYN之后,以自己的SYN应答,指定初始序列号ISN,ACK= SYN+1,发送ACK,服务器SYN_REVD状态
第三次,客户端收到SYN,发送ACK,再把服务端的ACK = ISN + 1 表示已经收到报文发送给服务端,两端状态都变为ESTABLISHED
![](https://img.haomeiwen.com/i11124643/d8d3f376cc98fde3.png)
常考题:
三次握手过程中可以携带数据吗
很多人可能会认为三次握手都不能携带数据,其实第三次握手的时候,是可以携带数据的。也就是说,第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。
为什么这样呢?大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据,因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发 SYN 报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。也就是说,第一次握手可以放数据的话,其中一个简单的原因就是会让服务器更加容易受到攻击了。
而对于第三次的话,此时客户端已经处于 established 状态,也就是说,对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据页没啥毛病。
为什么要三次握手,两次握手不可以吗?
两次的话,会出现这种情况,A发出的第一次连接请求报文段没有丢失,而是在某些网络节点长时间滞留,本来是早已失效的报文段,但B收到后误以为A发送的一次新的请求,如果是三次握手则会向A确认报文段,同意建立连接,两次握手则直接建立连接,这样就会导致新的连接建立,B的许多资源白白浪费。
四次挥手
1. 第一次挥手:客户端发送一个 FIN 报文段,FIN报文段表示断开连接的意思,报文中会指定一个序列号K。此时客户端处于 FIN_WAIT1 状态
2. 服务端将序列号K值加1作为ACK确认号返回值,表明接受到客户端报文。这时上层的应用程序会被告知另一端发起了关闭操作,上层进行关闭操作。此时服务端处于 CLOSE_WAIT 状态。客户端进入FIN_WAIT2(终止等待2)状态
3. 服务端发起自己的FIN报文段,ACK=K+1, Seq=L,seq是序号,此时服务端处于 LAST_ACK 的状态。
4. 客户端返回确认号ACK=L+1给服务端,客户端处于 CLOSED 状态,TCP连接断开。
常考题:
为什么建立连接只通信了三次,而断开连接却用了四次?
因为服务端收到FIN,发送ACK只是应答,并不代表服务端希望关闭连接。
当服务端把所有报文都发送完了,才发送FIN,告诉客户端可以关闭连接了。