zoukankan      html  css  js  c++  java
  • tcp ip 三次握手时数据结构-

    struct tcp_request_sock {
        struct inet_request_sock     req;
        const struct tcp_request_sock_ops *af_specific;
        struct skb_mstamp        snt_synack; /* first SYNACK sent time */
        bool                tfo_listener;
        u32                txhash;
        u32                rcv_isn;
        u32                snt_isn;
        u32                last_oow_ack_time; /* last SYNACK */
        u32                rcv_nxt; /* the ack # by SYNACK. For
                              * FastOpen it's the seq#
                              * after data-in-SYN.
                              */
    };
    
    
    
    struct inet_request_sock {
        struct request_sock    req;
    #define ir_loc_addr        req.__req_common.skc_rcv_saddr
    #define ir_rmt_addr        req.__req_common.skc_daddr
    #define ir_num            req.__req_common.skc_num
    #define ir_rmt_port        req.__req_common.skc_dport
    #define ir_v6_rmt_addr        req.__req_common.skc_v6_daddr
    #define ir_v6_loc_addr        req.__req_common.skc_v6_rcv_saddr
    #define ir_iif            req.__req_common.skc_bound_dev_if
    #define ir_cookie        req.__req_common.skc_cookie
    #define ireq_net        req.__req_common.skc_net
    #define ireq_state        req.__req_common.skc_state
    #define ireq_family        req.__req_common.skc_family
    
        kmemcheck_bitfield_begin(flags);
        u16            snd_wscale : 4,
                    rcv_wscale : 4,
                    tstamp_ok  : 1,
                    sack_ok       : 1,
                    wscale_ok  : 1,
                    ecn_ok       : 1,
                    acked       : 1,
                    no_srccheck: 1;
        kmemcheck_bitfield_end(flags);
        u32                     ir_mark;
        union {
            struct ip_options_rcu __rcu    *ireq_opt;
            struct sk_buff        *pktopts;
        };
    
    };
    
    
    /* struct request_sock - mini sock to represent a connection request
     */
    struct request_sock {
        struct sock_common        __req_common;
    #define rsk_refcnt            __req_common.skc_refcnt
    #define rsk_hash            __req_common.skc_hash
    #define rsk_listener            __req_common.skc_listener
    #define rsk_window_clamp        __req_common.skc_window_clamp
    #define rsk_rcv_wnd            __req_common.skc_rcv_wnd
    
        struct request_sock        *dl_next;
        u16                mss;
        u8                num_retrans; /* number of retransmits */
        u8                cookie_ts:1; /* syncookie: encode tcpopts in timestamp */
        u8                num_timeout:7; /* number of timeouts */
        u32                ts_recent;
        struct timer_list        rsk_timer;
        const struct request_sock_ops    *rsk_ops;
        struct sock            *sk;
        u32                *saved_syn;
        u32                secid;
        u32                peer_secid;
    };

    客户端主动发起连接

    •  调用 socket(2) 创建 TCP socket,tcp_sock 处于 CLOSE 状态
    • 调用 connect(2) 发起连接,tcp_sock 进入 SYN_SENT 状态。
      1. 选择 ephemeral port
      2. 创建 inet_bind_bucket 并加入 bhash
      3. 将 tcp_sock 加入 ehash
      4. 发送 SYN segment

     

    • 收到服务器发来的 SYN+ACK segment。
      1. 从 ehash 中找到 tcp_sock
      2. 完成握手,进入 ESTABLISHED 状态。数据结构不变,图略。
      3. 发送 ACK segment

    服务器被动接受连接

      1. 调用 socket(2) 创建 TCP socket,tcp_sock 处于 CLOSE 状态。数据结构如图二。
      2. 调用 bind(2) 将 tcp_sock 加入 bhash。
      3. 调用 listen(2) 将 tcp_sock 设为 LISTEN 状态,并加入 listening_hash。
        这时数据结构的状态如下图:

      1. 调用 socket(2) 创建 TCP socket,tcp_sock 处于 CLOSE 状态。数据结构如图二。
      2. 调用 bind(2) 将 tcp_sock 加入 bhash。
      3. 调用 listen(2) 将 tcp_sock 设为 LISTEN 状态,并加入 listening_hash。
        这时数据结构的状态如下图:
        原图:
      4. 收到 SYN segment,从 listening_hash 找到 listen tcp_sock,创建 tcp_request_sock(NEW_SYN_RECV 状态),并将其加入 ehash,然后发送 SYN+AC
      5.  收到 ACK segment,从 ehash 中找到 tcp_request_sock,顺藤摸瓜找到 listen tcp_sock,创建新的 tcp_sock(SYN_RECV 状态),将其链入 listen tcp_sock 所属的 inet_bind_bucket 中,然后用它替换 tcp_request_sock 在 ehash 中的位置。接下来把 tcp_request_sock 加入 listen socket 的 accept queue 中,最后经过一系列处理,把新 tcp_sock 设为 ESTABLISHED 状态,可以接收数据了。

      6. 用户程序调用 accept(2),从 listen socket 的 accept queue 中取出新 tcp_sock,销毁 tcp_request_sock,然后创建 file/dentry/socket_alloc 等对象将 tcp_sock 加入进程的文件描述符表中,返回相应的文件描述符。

    与以前的版本相比,第 4 步改动最大,原来是把 tcp_request_sock 挂在 listen socket 下,收到 ACK 之后从 listening_hash 找到 listen socket 再进一步找到 tcp_request_sock;新的做法是直接把 tcp_request_sock 挂在 ehash 中,这样收到 ACK 之后可以直接找到 tcp_request_sock,减少了锁的争用(contention)。具体的 commit 是:

     

    http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!! 但行好事 莫问前程 --身高体重180的胖子
  • 相关阅读:
    2. Add Two Numbers
    1. Two Sum
    leetcode 213. 打家劫舍 II JAVA
    leetcode 48. 旋转图像 java
    leetcode 45. 跳跃游戏 II JAVA
    leetcode 42. 接雨水 JAVA
    40. 组合总和 II leetcode JAVA
    24. 两两交换链表中的节点 leetcode
    1002. 查找常用字符 leecode
    leetcode 23. 合并K个排序链表 JAVA
  • 原文地址:https://www.cnblogs.com/codestack/p/14883810.html
Copyright © 2011-2022 走看看