TCP在收到FIN时,会调用tcp_data_queue函数进行处理:
4300 static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
4301 {
4302 const struct tcphdr *th = tcp_hdr(skb);
4303 struct tcp_sock *tp = tcp_sk(sk);
4304 int eaten = -1;
4305 bool fragstolen = false;
...
4321 if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) { //正序包
...
4344 if (eaten <= 0) { //没有在进程上下文中被提前copy进用户缓存
4345 queue_and_out:
4346 if (eaten < 0 &&
4347 tcp_try_rmem_schedule(sk, skb, skb->truesize))
4348 goto drop;
4349
4350 eaten = tcp_queue_rcv(sk, skb, 0, &fragstolen); //放入接收队列中
4351 }
4352 tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
4353 if (skb->len)
4354 tcp_event_data_recv(sk, skb);
4355 if (th->fin)
4356 tcp_fin(sk); //处理FIN包
4357
4358 if (!skb_queue_empty(&tp->out_of_order_queue)) {
4359 tcp_ofo_queue(sk);
...
乱序包会在
tcp_ofo_queue函数整合时处理FIN标记:
4023 static void tcp_ofo_queue(struct sock *sk)
4024 {
4025 struct tcp_sock *tp = tcp_sk(sk);
4026 __u32 dsack_high = tp->rcv_nxt;
4027 struct sk_buff *skb;
...
4050 __skb_unlink(skb, &tp->out_of_order_queue);
4051 __skb_queue_tail(&sk->sk_receive_queue, skb);
4052 tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
4053 if (tcp_hdr(skb)->fin)
4054 tcp_fin(sk);
4055 }
4056 }
看来FIN包的处理是由tcp_fin完成的:
3783 static void tcp_fin(struct sock *sk)
3784 {
3785 struct tcp_sock *tp = tcp_sk(sk);
3786
3787 inet_csk_schedule_ack(sk);
3788
3789 sk->sk_shutdown |= RCV_SHUTDOWN; //不允许再接受数据,因为对端不会再发送数据了
3790 sock_set_flag(sk, SOCK_DONE);
3791
3792 switch (sk->sk_state) {
3793 case TCP_SYN_RECV:
3794 case TCP_ESTABLISHED: //未发送FIN就收到FIN
3795 /* Move to CLOSE_WAIT */
3796 tcp_set_state(sk, TCP_CLOSE_WAIT);
3797 inet_csk(sk)->icsk_ack.pingpong = 1; //延迟回复ACK,期望发送数据或FIN时携带ACK确认
3798 break;
3799
3800 case TCP_CLOSE_WAIT:
3801 case TCP_CLOSING:
3802 /* Received a retransmission of the FIN, do
3803 * nothing.
3804 */
3805 break;
3806 case TCP_LAST_ACK: //重传的FIN
3807 /*