1. linux查看TCP状态
- netstat -nat : 查看TCP链接的状态
- lsof -i:port 查看打开套接字的状态
- tcpdump -Xns0 -i any tcp port 20789
2. TCP状态转换
一共11种状态
2.1 客户端状态迁移
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
2.2 服务端状态迁移
CLOSED->LISTEN->SYN_RCVD->ESTABLISTED->CLOSE_WAIT->LAST_ACK->CLOSED
3 TCP三次握手状态
3.1 正常打开
- 客户端:CLOSED(socket创建)---> SYN_SENT(connect阻塞调用,发送SYN)----> ESTABLISHED(connect返回,接收:SYN,ACK,发送:ACK)
- 服务端:CLOSED(socket创建)---> LISTEN(bind,listen被动打开) --->SYN_RCVD(accept阻塞) ---> ESTABLISTED(accept返回,接收:SYN,发送:SYN,ACK)
握手过程
状态转换
3.2 同时打开
- 在SYN_SENT状态收到SYN变为SYN_RCVD状态,再收到ACK变为ESTABLISTED
- 代码中两边同时调用CONNECT?
握手过程
状态转换
3.3 连接超时或者RST复位
- 客户端发送SYN后,没有收到服务端响应,重试net.ipv4.tcp_syn_retries(6次)后超时回到CLOSED状态
1+2+4+8+16+32+64=127
- 服务端发 SYN+ACK后,重试net.ipv4.tcp_synack_retries回到LISTEN状态
- 客服端connect之后立马调用close,服务端发送SYN,ACK后会收到客户端内核返回的一个RST
握手过程
状态转换
4. 四次挥手
4.1 正常关闭
- 客户端: ESTABLISTED -->FIN_WAIT_1(调用CLOSE,发送FIN) -->FIN_WAIT_2(收到服务端ACK)-->TIME_WAIT(收到FIN) --> CLOSED(2msl后)
- 服务端:ESTABLISTED-->CLOSE_WAIT(read返回0,收到FIN,发送ACK)-->LAST_ACK(调用close,发送FIN)-->CLOSED(收到ack)
挥手过程
状态转换
4.2 同时关闭
- 在FIN_WAIT_1状态接受到一个FIN,进入CLOSING,用于等待ACK,收到后进入CLOSE_WAIT状态
- 客户端、服务端同时调用close
挥手过程
状态转换
4.3 四次挥手合并为三次挥手
- 服务端同时发送FIN+ACK,导致客户端直接公FIN_WAIT_1进入TIME_WAIT状态
- 一般是因为内核ACK确认延迟,同FIN包一起返回