常见的业务故障或者性能瓶颈大多数都是TCP连接问题造成的,所以细致的理解各个tcp状态非常方便排障。
TCP三次握手链接状态:
- 客户端像服务端发送请求连接包,标识位为SYN,seq=x, 客户端状态SYN_SEND
- 服务端收到消息SYN包,需要客户端确认一次,所以回了一个数据包, 标识位为SYN+ACK,seq=y,ackno=x+1,服务端状态为SYN_RECV
- 客户端收到服务端发来的包,验证ackno为x+1,确认链接已建立完成, 回复服务端,标识位ACK(seq=x+1,ackno=y+1),客户端和服务端均为ESTABLISHED状态
TCP四次挥手链接状态:(这里的客户端为主动要求关闭方)
- 客户端发送一个释放请求,标识位(seq=u)到服务端,要求中断连接,再未收到ACK之前,依然收数据,此时状态为FIN-WAIT-1
- 服务端收到请求后,发送一个标识位为ACK给对方,seq=u+1 ,ackno = y,服务端状态为CLOSE-WAIT,客户端收到ACK后,将状态改为FIN-WAIT-2
- 服务端从上一个ACK发完以后,确认数据包已传完,可以关闭了,再次发送TCP报文到客户端, 标记位为FIN和ACK, seq=w,ackno=u+1,服务端的状态为LAST-ACK
- 客户端收到后,再次发送一个标识位为ACK的TCP报文,seq=u+1,ackno=w+1,客户端进入TIME-WAIT 等待2MSL,服务端收到后状态改为CLOSED,2MSL后客户端也变成CLOSED
time_wait存在的意义:
- 客户端最后发送一个ACK报文后,不确认服务端是否收到,服务端基于TCP的重传机制,在2MSL周期内如果没收到ACK会重新发送一个FIN包到客户端,客户端收到后再发一个ACK到服务端并重置MSL计时器
- 保持TCP链接的唯一性,如没有TIME_WAIT,新开的链接会被认为是一个之前那个链接,导致发送了上一个链接理论上已经不需要的数据
- MSL时间多久, 实际应用中常用的是30秒, 1分钟和2分钟等