<span style="font-size:32px;">结论</span>
tcp客户端connect发起之后,协议栈就会发送SYN给服务器,协议栈收到来自服务器的响应后,发出Ack后,就进入了established
tcp服务器在收到SYN后,发送SYN+ACK后就进入SYN_RECVD,再次收到客户端的Ack时,也进入established
established状态连接的双方进入的时机是有先后的,客户端是先进入的,服务器是后进入的
connect系统调用过程
SYSCALL_DEFINE2(socketcall)(net/socket.c)
SYSCALL_DEFINE3(connect)(net/socket.c)
inet_stream_connect(net/ipv4/af_inet.c)
tcp_v4_connect(net/ipv4/tcp_ipv4.c)
{
......
tcp_set_state(sk, TCP_SYN_SENT);
.......
}
tcp_connect(net/ipv4/tcp_output.c)
inet_wait_for_connect(net/ipv4/af_inet.c)
{
//一直在等待状态变化,或者是established,close,循环才会出来
while ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
release_sock(sk);
timeo = schedule_timeout(timeo);
lock_sock(sk);
if (signal_pending(current) || !timeo)
break;
prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
}
finish_wait(sk->sk_sleep, &wait);
return timeo;
}
状态如何变化为Established
tcp_v4_rcv(net/ipv4/tcp_ipv4.c)
tcp_v4_do_rcv(net/ipv4/tcp_ipv4.c)
tcp_rcv_state_process(net/ipv4/tcp_input.c)
tcp_rcv_synsent_state_process(net/ipv4/tcp_input.c)
{
....
TCP_ECN_rcv_synack(tp, th);
tcp_set_state(sk, TCP_ESTABLISHED);
if (!sock_flag(sk, SOCK_DEAD))
{
sk->sk_state_change(sk);//唤醒等待的进程
sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT);
}
......
tcp_send_ack(sk);
....
}
收到来自服务器的SYN+ACK,就会进入ESTABLISHED状态,然后发送ACK给服务器
另外补充一下状态机的认识
主动关闭的一方,不能期待对方马上关闭,因为对方可能还有数据要传输
多以Peer端要等待关闭close_wait
主动关闭的一方需要等待对方的fin,所以要进入fin_wait
以及为了避免对方重传的fin来关闭新的连接,一定要经过time_wait周期后之链路上面非常干净
time_wait也可以避免seq序号的回绕