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 }

 

posted @ 2019-10-28 11:33  AlexAlex  阅读(756)  评论(0编辑  收藏  举报