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的胖子
  • 相关阅读:
    将才和帅才之的区别
    百胜集团XX:BPM实现业务流程全过程无缝链接(案例)
    心、肝、脾、肺、肾五脏解说+ 五脏六腑的作用
    人体的五行属性
    易经卦的通例
    《孙子兵法》中的企业领导艺术和方法
    五行盘谱
    大容量高并发性服务器组的技术解析
    中华哲学的领导艺术
    如何在WINDOW环境下搭建ActivateMQ和zookeeper集群环境
  • 原文地址:https://www.cnblogs.com/codestack/p/14883810.html
Copyright © 2011-2022 走看看