三握四挥过程及扩展面试题
三次握手
假设A和B分别是客户端和服务器,事实上A和B任何一方都可以发起建立连接的请求。
-
建立连接前:
A 和 B 均处于 CLOSED 状态,B 会创建传输控制块 TCB 并进入 LISTEND 状态,监听端口是否收到 TCP 请求。
-
第一次握手:
A 向 B 发送连接请求报文:SYN=1,ACK=0,此时不可以携带数据,但要消耗一个随机序号seq = x。发送完后 A 进入 SYN-SENT 同步已发送状态。
-
第二次握手:
B 收到 A 的连接请求报文后,为该TCP连接分配资源。如果同意建立连接就会发送给 A 一个确认连接请求报文:SYN=1,ACK=1是确认号,确认收到了客户端的包,并且会设一个seq=y随机序号。ack=x+1表示接下来希望客户端要发的数据从哪开始。发送完后B进入 SYN-RCVD 同步已接收状态。
-
第三次握手:
A 收到 B 的确认连接请求报文后,为该TCP连接分配资源,并给服务器端返回确认。此时SYN=0,意思这不是建立连接的请求了,要正式发数据了,ACK=1是确认号,确认收到了服务端的包。seq=x+1, ack=y+1,此报文可以携带数据。发送后 A 进入 ESTABLISHED 状态,当 B 接收到该报文后也进入 ESTABLISHED 状态,客户端会稍早于服务端建立连接。
此时连接建立成功,可以使用全双工的方式进行数据传送。
四次挥手
-
第一次挥手:
A 没有要发送的数据时会向 B 发送一个连接释放报文,其中 FIN=1,表明客户端已经完成了数据的发送,并要求释放链接。**seq=u,**u是A传送数据最后一个字节的序号+1。发送完之后进入 FIN-WAIT-1 终止等待1状态。
-
第二次挥手:
B 收到该报文后,返回确认报文,ACK=1,ack=u+1,seq=v,v 是B传送数据最后一个字节的序号+1。此时A不能给B发送数据,只能接收;B仍然能给A传送数据。此时 A 进入FIN-WAIT-2 状态,B 进入 CLOSE-WAIT 状态。
-
第三次挥手:
B也发完数据之后,向 A 发送连接释放报文,FIN=1,ACK=1,ack=u+1,seq=w,w是B传送数据最后一个字节的序号+1,之后 B 进入 LAST-ACK 状态。
-
第四次挥手:
A收到连接释放报文后返回确认报文:ACK=1,ack=w+1,seq=u+1。发送完之后进入 TIME-WAIT 状态,等待 2MSL之后进入 CLOSED 状态,B 收到该确认后进入 CLOSED 状态,服务端会稍早于客户端释放连接。
扩展面试题
-
为什么是三次握手?
建立连接时需要服务器和客户端分别为对方的起始序列号做确认,保证传输的可靠性。
如果缺少一次握手,客户端并没有太大的变化,仍然需要获得服务端的应答后才进入ESTABLISHED状态,而服务端在收到连接请求后就进入ESTABLISHED状态。此时如果网络拥塞,客户端发送的连接请求1迟迟到不了服务端,客户端便超时重发请求2,如果服务端正确接收请求2并确认应答,双方便开始通信,通信结束后释放连接。此时,如果请求1抵达了服务端,服务端会再次进入ESTABLISHED状态,但此时的客户端早已进入CLOSED状态,服务端将会一直等待下去,浪费服务端连接资源。
-
为什么是四次挥手?
关闭连接时,己方收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了。所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接。因此,己方ACK和FIN一般都会分开发送,从而导致四次挥手。
-
为什么四次挥手要等待两个时间周期?
如果服务器没有接收到客户端的最后一个ACK,服务器就会超时重传FIN,客户端会重新返回最后一个ACK报文。如果不等待两个时间周期,服务器重传的那条消息就不会收到。服务器就因为接收不到客户端的信息而无法正常关闭。
-
什么是SYN洪泛攻击?
攻击者发送TCP的SYN,而当服务器返回ACK后,攻击者不对其进行再确认,那这个TCP连接就处于挂起状态,服务器收不到再确认的话,还会重复发送ACK给攻击者。这样更加会浪费服务器资源。攻击者就对服务器发送大量的这种TCP连接,由于每一个连接都无法完成三次握手,所以就在服务器上,这些TCP连接会因为挂起状态而消耗CPU和内存,最后服务器可能死机。
-
三次握手的第一次可以携带数据吗?
不可以,如果攻击者伪造了成千上万的握手报文,携带了许多数据,接收方会开辟大量的缓存来容纳这些巨大数据,内存会很容易耗尽,从而拒绝服务。