目录
1.四次挥手
图 1
第一次挥手
客户端发送FIN报文
FIN标识:1,seq(序号):M
作用:客户端准备释放TCP连接并通知服务端,客户端主动关闭TCP连接
第二次挥手
服务端发送ACK报文
ACK标识:1,ack(确认号):M+1
作用:释放客户端往服务端方向连接,TCP连接处于半关闭状态,客户端不能再发送数据给服务端
第三次挥手
服务端发送FIN报文
FIN标识:1,seq(序号):N
作用:服务端数据包发送完毕,通知客户端释放TCP连接
第四次挥手
客户端发送ACK报文
ACK标识:1,ack(确认号):N+1
作用:通知服务端关闭TCP连接,客户端进入TIME_WAIT,需等TIME_WAIT结束才能关闭TCP连接
2.为什么挥手需要四次?
TCP是全双工协议,TCP连接终止需要释放两个方向的连接
前两次挥手关闭客户端发往服务端的连接,后两次挥手关闭服务端发往客户的连接,因为收到客户端FIN报文,服务端可能还有数据未发送完,所以不会立马发送ACK报文,所以挥手需要四次。
3.为什么需要TIME_WAIT状态?
3.1保证TCP全双工连接终止不出错
图 2
客户端收到第三次挥手后,进入TIME_WAIT状态,但是服务端还处于LAST_ACK状态,需要收到客户端ACK报文,才能关闭TCP连接,如果服务端没有收到ACK报文,服务端误认为客户端没有收到FIN报文,所以服务端重传FIN报文,直到收到ACK报文为止。
客户端需要TIME_WAIT状态,目的能够让服务端重传FIN报文,并回复ACK报文,完成服务端TCP连接释放。
3.2 防止旧的连接还未终止,新的连接开始建立
图 3
TCP旧的连接未终止,不能建立新的连接,TIME_WAIT状态为了使客户端连接存活时间增长。
如果没有TIME_WAIT状态或者TIME_WAIT时间过短,客户端收到FIN报文后,很快切换为CLOSED状态,客户端可以建立新的四元组相同的TCP连接(四元组:源IP,目的IP,源端口,目的端口),然而服务端还处于LAST_ACK状态,无法处理新的连接请求。
4.为什么TIME_WAIT等待时间是2MSL?
MSL(maximum segment lifetime),报文的最大生存时间,RFC1122建议值为2分钟,也有30秒的情况,MSL是根据IP首部TTL计算而来,TTL为跳数,MSL必须大于TTL对应的时间。
2MSL:两个报文最大生存时间(往返报文),持续时间为1-4分钟
由于网络异常,导致TCP数据包发生重传,旧的数据包可能并没有被丢弃,而滞留在网络中,随着网络修复(修复时间通常为几秒或者几分钟),最终旧的数据包被服务端收到,如果旧报文是一个连接请求,旧的连接请求和新的连接请求可能冲突,TIME_WAIT设置为2MSL,为了确保往返两个方向旧报文随着TTL消耗完而丢弃,从而完全隔离了新连接和旧连接数据包。
5.TIME_WAIT过多有什么危害?
对于客户端来说,TIME_WAIT过多意味着大量连接未释放,未释放的连接占用着系统资源(内存,文件描述符,端口号等),造成系统资源浪费。对于服务端,连接可能处于LAST_ACK状态,同样占据着系统资源,如果海量TIME_WAIT对应的是同一台服务器,服务器可能过载瘫痪。
6.为什么连接的时候是三次握手,关闭的时候却是四次挥手?
三次握手:第二次握手是服务端发送SYN+ACK报文,该报文同时完成对客户端SYN请求的应答,也完成了服务端SYN请求报文发送。
四次挥手:第二次挥手和第三次挥手在服务端有数据未发送的情况下,不能组成FIN+ACK报文发送,所以挥手需要四次。
7.TCP四次挥手中间两次会合并成一次吗?
图 4
会的
情况1:第一次挥手后,服务端数据已经发送完毕,有可能发送FIN+ACK包,同时应答客户端FIN报文,和发送FIN报文,该情况很少见。
情况2:服务端开启了TCP延迟确认,服务端收到客户端FIN报文后,不会立即应答ACK,而是会和下一个数据包一起应答,从而会发送FIN+ACK报文,该情况很常见,wireshark抓包经常能抓到。