zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Java 基础(接口的应用:代理模式 Proxy)
    Appium 环境配置
    破解CCleaner
    数据驱动
    (C语言内存二十)C语言内存泄露(内存丢失)
    (C语言内存十九)C语言野指针以及非法内存操作
    (C语言内存十八)malloc函数背后的实现原理——内存池
    (C语言内存十七)栈溢出攻击的原理是什么?
    (C语言内存十六)C语言动态内存分配
    (C语言内存十五)用一个实例来深入剖析函数进栈出栈的过程
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11751246.html
Copyright © 2011-2022 走看看