TCP连接建立 之 同时打开
假设两台设备双方均发送syn给对端,在发送syn之后状态处于SYN_SENT状态,此时双方均收到对端的发来的syn,则立即进入SYN_RECV状态,并且都向对端回复syn+ack,在收到syn+ack之后,连接从SYN_RECV状态切换到ESTABLISHED状态;
在发送syn进入SYN_SENT状态之后,收到对端发来的syn包处理流程如下,调用tcp_set_state(sk, TCP_SYN_RECV)进入SYN_RECV状态,以及调用tcp_send_synack(sk)向对端发送syn+ack;
1 static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, 2 const struct tcphdr *th) 3 { 4 if (th->syn) { 5 /* We see SYN without ACK. It is attempt of 6 * simultaneous connect with crossed SYNs. 7 * Particularly, it can be connect to self. 8 */ 9 tcp_set_state(sk, TCP_SYN_RECV); 10 11 if (tp->rx_opt.saw_tstamp) { 12 tp->rx_opt.tstamp_ok = 1; 13 tcp_store_ts_recent(tp); 14 tp->tcp_header_len = 15 sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED; 16 } else { 17 tp->tcp_header_len = sizeof(struct tcphdr); 18 } 19 20 tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; 21 tp->copied_seq = tp->rcv_nxt; 22 tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1; 23 24 /* RFC1323: The window in SYN & SYN/ACK segments is 25 * never scaled. 26 */ 27 tp->snd_wnd = ntohs(th->window); 28 tp->snd_wl1 = TCP_SKB_CB(skb)->seq; 29 tp->max_window = tp->snd_wnd; 30 31 tcp_ecn_rcv_syn(tp, th); 32 33 tcp_mtup_init(sk); 34 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); 35 tcp_initialize_rcv_mss(sk); 36 37 tcp_send_synack(sk); 38 }
在SYN_RECV状态收到对端发来的syn+ack包,则直接进入ESTABLISHED已连接状态;
1 int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) 2 { 3 /* step 5: check the ACK field */ 4 acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH | 5 FLAG_UPDATE_TS_RECENT) > 0; 6 7 switch (sk->sk_state) { 8 case TCP_SYN_RECV: 9 10 /* ack处理失败 */ 11 if (!acceptable) 12 return 1; 13 14 /* RTT */ 15 if (!tp->srtt_us) 16 tcp_synack_rtt_meas(sk, req); 17 18 /* Once we leave TCP_SYN_RECV, we no longer need req 19 * so release it. 20 */ 21 if (req) { 22 inet_csk(sk)->icsk_retransmits = 0; 23 reqsk_fastopen_remove(sk, req, false); 24 } else { 25 /* Make sure socket is routed, for correct metrics. */ 26 /* 检查重建路由 */ 27 icsk->icsk_af_ops->rebuild_header(sk); 28 /* 初始化拥塞邋控制 */ 29 tcp_init_congestion_control(sk); 30 /* 路径mtu发现初始化 */ 31 tcp_mtup_init(sk); 32 /* 用户待读取数据初始化 */ 33 tp->copied_seq = tp->rcv_nxt; 34 /* 调整接收发送缓存以及窗口等 */ 35 tcp_init_buffer_space(sk); 36 } 37 smp_mb(); 38 39 /* 连接更新为已连接状态 */ 40 tcp_set_state(sk, TCP_ESTABLISHED); 41 sk->sk_state_change(sk); 42 /* 省略了一些代码 */ 43 }