客户端接收到服务端发送的SYN+ACK包后,依然会走到tcp_rcv_state_process方法中,此时客户端是SYN_SENT状态,调用tcp_rcv_synsent_state_process继续处理。
tcp_rcv_synsent_state_process中调用tcp_finish_connect将客户端状态改成设置为TCP_ESTABLISHED状态;调用tcp_send_ack继续处理。
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_mask(sk, GFP_ATOMIC | __GFP_NOWARN));
if (unlikely(!buff)) {
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);
/* We do not want pure acks influencing TCP Small Queues or fq/pacing
* too much.
* SKB_TRUESIZE(max(1 .. 66, MAX_TCP_HEADER)) is unfortunately ~784
*/
skb_set_tcp_pure_ack(buff);
/* Send it off, this clears delayed acks for us. */
tcp_transmit_skb(sk, buff, 0, (__force gfp_t)0);
}
此函数中主要的逻辑有:
1. 调用alloc_skb申请sk_buff结构;
2. 在tcp_init_nondata_skb中将TCP_SKB_CB(skb)->tcp_flags置为TCPHDR_ACK;
#define TCPHDR_ACK 0x10
3. 调用tcp_transmit_skb组装tcp头和ip头并发送。
以下为tcp_transmit_skb中设置tcp头的地方:
th->source = inet->inet_sport; // 源端口
th->dest = inet->inet_dport; // 目标端口
th->seq = htonl(tcb->seq);
th->ack_seq = htonl(tp->rcv_nxt);
// 设置首部长度和ACK标记
*(((__be16 *)th) + 6) = htons(((tcp_header_size >> 2) << 12) |
tcb->tcp_flags);
ip_queue_xmit中调用ip_copy_addrs,设置源/目标地址
memcpy(&iph->saddr, &fl4->saddr, sizeof(fl4->saddr) + sizeof(fl4->daddr));
最后在ip_queue_xmit中调用ip_local_out将数据包发送出去。
二 服务端接收ACK
还是回到服务端tcp_rcv_state_process函数中,此时服务端处于SYN_RCVD状态,走TCP_SYN_RECV分支。
tcp_set_state(sk, TCP_ESTABLISHED); 设置为ESTABLISHED状态