握手5

当发现 tcp 头部的 ACK 为 1 ,则进入下面函数处理 ,重点看一下:tcp_finish_connect

void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
{
    struct tcp_sock *tp = tcp_sk(sk);
    struct inet_connection_sock *icsk = inet_csk(sk);

    tcp_set_state(sk, TCP_ESTABLISHED);// 设置 sock 的状态 为 TCP_ESTABLISHED 

    if (skb != NULL) {
        icsk->icsk_af_ops->sk_rx_dst_set(sk, skb);
        security_inet_conn_established(sk, skb);
    }

    /* Make sure socket is routed, for correct metrics.  */
    icsk->icsk_af_ops->rebuild_header(sk);

    tcp_init_metrics(sk);

    tcp_init_congestion_control(sk);

    /* Prevent spurious tcp_cwnd_restart() on first data
     * packet.
     */
    tp->lsndtime = tcp_time_stamp;

    tcp_init_buffer_space(sk);

    if (sock_flag(sk, SOCK_KEEPOPEN))
        inet_csk_reset_keepalive_timer(sk, keepalive_time_when(tp));

    if (!tp->rx_opt.snd_wscale)
        __tcp_fast_path_on(tp, tp->snd_wnd);
    else
        tp->pred_flags = 0;

    if (!sock_flag(sk, SOCK_DEAD)) {
        sk->sk_state_change(sk);//默认函数为 sock_def_wakeup
  1. sock状态改变时调用,比如从TCP_SYN_SENT或TCP_SYN_RECV变为TCP_ESTABLISHED, 
  2. * 导致connect()的唤醒。比如从TCP_ESTABLISHED变为TCP_CLOSE_WAIT

        sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT);// 用来将SIGIO或SIGURG信号发送给在该套接口上的进程,通知该进程可以对该文件进行读或写.
    }
}

对 sock 的状态修改完后 会效用如下函数

void tcp_send_ack(struct sock *sk)
{
    struct sk_buff *buff;

    /* If we have been reset, we may not send again. */
    if (sk->sk_state == TCP_CLOSE)
        return;

    tcp_ca_event(sk, CA_EVENT_NON_DELAYED_ACK);

    /* We are not putting this on the write queue, so
     * tcp_transmit_skb() will set the ownership to this
     * sock.
     */
    buff = alloc_skb(MAX_TCP_HEADER, sk_gfp_atomic(sk, GFP_ATOMIC));
    if (buff == NULL) {
        inet_csk_schedule_ack(sk);
        inet_csk(sk)->icsk_ack.ato = TCP_ATO_MIN;
        inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
                      TCP_DELACK_MAX, TCP_RTO_MAX);
        return;
    }

    /* Reserve space for headers and prepare control bits. */
    skb_reserve(buff, MAX_TCP_HEADER);
    tcp_init_nondata_skb(buff, tcp_acceptable_seq(sk), TCPHDR_ACK);

    /* Send it off, this clears delayed acks for us. */
    skb_mstamp_get(&buff->skb_mstamp);
    tcp_transmit_skb(sk, buff, 0, sk_gfp_atomic(sk, GFP_ATOMIC));
}

构造一个 tcp 报文发送给服务器端。

原文地址:https://www.cnblogs.com/guoyu1024/p/10597066.html