7.4 FIN及其ACK的接收

        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         /* RFC793: Remain in the LAST-ACK state. */
3808         break;
3809
3810     case TCP_FIN_WAIT1:  //同时关闭
3811         /* This case occurs when a simultaneous close
3812          * happens, we must ack the received FIN and
3813          * enter the CLOSING state.
3814          */
3815         tcp_send_ack(sk);//发送ACK
3816         tcp_set_state(sk, TCP_CLOSING);
3817         break;
3818     case TCP_FIN_WAIT2:  
3819         /* Received a FIN -- send ACK and enter TIME_WAIT. */
3820         tcp_send_ack(sk);//发送ACK
3821         tcp_time_wait(sk, TCP_TIME_WAIT, 0);//进入TCP_TIME_WAIT状态
3822         break;
3823     default:
3824         /* Only TCP_LISTEN and TCP_CLOSE are left, in these
3825          * cases we should never reach this piece of code.
3826          */
3827         pr_err("%s: Impossible, sk->sk_state=%d\n",
3828                __func__, sk->sk_state);
3829         break;
3830     }
3831
3832     /* It _is_ possible, that we have something out-of-order _after_ FIN.
3833      * Probably, we should reset in this case. For now drop them.
3834      */
3835     __skb_queue_purge(&tp->out_of_order_queue); //收到FIN了,乱序队列中的数据就没有用了,因为FIN必然是按序到达
3836     if (tcp_is_sack(tp))  //开启了SACK选项
3837         tcp_sack_reset(&tp->rx_opt); //清除SACK选项信息,因为对端已经不会再发送数据了
3838     sk_mem_reclaim(sk); //将socket内存池中的内存返还给TCP全局内存
3839
3840     if (!sock_flag(sk, SOCK_DEAD)) {
3841         sk->sk_state_change(sk); //调用sock_def_wakeup唤醒进程
3842
3843         /* Do not send POLL_HUP for half duplex close. */
3844         if (sk->sk_shutdown == SHUTDOWN_MASK ||
3845             sk->sk_state == TCP_CLOSE)
3846             sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_HUP);
3847         else
3848             sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
3849     }
3850 }
        进程被唤醒后,会使用收包系统调用收数据:

 1545 int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
1546         size_t len, int nonblock, int flags, int *addr_len)
1547 {   
1548     struct tcp_sock *tp = tcp_sk(sk);
1549     int copied = 0;
1550     u32 peek_seq;
1551     u32 *seq;
1552     unsigned long used;
1553     int err;
1554     int target;     /* Read at least this many bytes */
1555     long timeo;
1556     struct task_struct *user_recv = NULL;
1557     bool copied_early = false;
1558     struct sk_buff *skb;
1559     u32 urg_hole = 0;  
...
1643             offset = *seq - TCP_SKB_CB(skb)->seq;
1644             if (tcp_hdr(skb)->syn)
1645                 offset--;
1646             if (offset < skb->len)
1647                 goto found_ok_skb;
1648             if (tcp_hdr(skb)->fin) //没有数据的FIN包
1649                 goto found_fin_ok;
...
1873 skip_copy:
1874         if (tp->urg_data && after(tp->copied_seq, tp->urg_seq)) {
1875             tp->urg_data = 0;
1876             tcp_fast_path_check(sk);
1877         }
1878         if (used + offset < skb->len)
1879             continue;
1880
1881         if (tcp_hdr(skb)->fin)//数据包中携带FIN标记
1882             goto found_fin_ok;
1883         if (!(flags & MSG_PEEK)) {
1884             sk_eat_skb(sk, skb, copied_early);
1885             copied_early = false;
1886         }
1887         continue;
1888
1889     found_fin_ok:
1890         /* Process the FIN. */    
1891         ++*seq;
1892         if (!(flags & MSG_PEEK)) {
1893             sk_eat_skb(sk, skb, copied_early); //释放skb,下次就会读到0字节
1894             copied_early = false;
1895         }
1896         break;
1897     } while (len > 0); 
        如果收包队列中只有无数据的FIN包,则收包系统会调用返回0,这时应用进程就知道收到了FIN,对端关闭了连接。如果队列中有数据则系统调用会返回大于0的值 ,然后 应用进程如果调用事件监听函数(如epoll_wait)等待数据到来,这时会调用tcp_poll函数:

 433 unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
 434 {               
 435     unsigned int mask;
 436     struct sock *sk = sock->sk;
 437     const struct tcp_sock *tp = tcp_sk(sk);
...
 479     if (sk->sk_shutdown & RCV_SHUTDOWN) //在tcp_fin函数的3789行设置了RCV_SHUTDOWN标记,故判断为真
 480         mask |= POLLIN | POLLRDNORM | POLLRDHUP;
...
 524     return mask;
 525 }
        tcp_poll会返回POLLIN事件,进程则会再次调用 收包系统调用 读包,但 由于此时收包队列为空, 收包系统调用 会返回0,应用进程还是能够知道发生了连接关闭事件。
        FIN的接收流程分析完了,现在来看对FIN的ACK的接收流程。发送FIN的一端收到ACK后,会调用tcp_rcv_state_process函数进行处理:
 5600 int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
5601               const struct tcphdr *th, unsigned int len)
5602 {
5603     struct tcp_sock *tp = tcp_sk(sk);
5604     struct inet_connection_sock *icsk = inet_csk(sk);
5605     struct request_sock *req;
5606     int queued = 0;      
...
5677     if (true) {
5678         int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH |
5679                           FLAG_UPDATE_TS_RECENT) > 0;
5680
5681         switch (sk->sk_state) {
...
5751         case TCP_FIN_WAIT1:
5752             /* If we enter the TCP_FIN_WAIT1 state and we are a
5753              * Fast Open socket and this is the first acceptable
5754              * ACK we have received, this would have acknowledged
5755              * our SYNACK so stop the SYNACK timer.
5756              */
5757             if (req != NULL) { //还有FAST OPEN的request sock没有处理
5758                 /* Return RST if ack_seq is invalid.
5759                  * Note that RFC793 only says to generate a
5760                  * DUPACK for it but for TCP Fast Open it seems
5761                  * better to treat this case like TCP_SYN_RECV
5762                  * above.
5763                  */
5764                 if (!acceptable)
5765                     return 1;
5766                 /* We no longer need the request sock. */
5767                 reqsk_fastopen_remove(sk, req, false);
5768                 tcp_rearm_rto(sk);
5769             }
5770             if (tp->snd_una == tp->write_seq) { //FIN已经被确认
5771                 struct dst_entry *dst;
5772
5773                 tcp_set_state(sk, TCP_FIN_WAIT2); //状态跳转到TCP_FIN_WAIT2
5774                 sk->sk_shutdown |= SEND_SHUTDOWN;
5775
5776                 dst = __sk_dst_get(sk);
5777                 if (dst)
5778                     dst_confirm(dst);
5779
5780                 if (!sock_flag(sk, SOCK_DEAD))
5781                     /* Wake up lingering close() */
5782                     sk->sk_state_change(sk);
5783                 else { //socket已经DEAD,这意味中当前sock已经是orphan sock
5784                     int tmo;
5785
5786                     if (tp->linger2 < 0 || //用户设置了TCP_LINGER2选项的值小于0
5787                         (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && //包中有数据或FIN标记位
5788                          after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) { //有新数据
5789                         tcp_done(sk);//彻底关闭连接
5790                         NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
5791                         return 1;
5792                     }
5793
5794                     tmo = tcp_fin_time(sk);//计算超时时间
5795                     if (tmo > TCP_TIMEWAIT_LEN) {//超时时间大于time_wait的时间
5796                         inet_csk_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN);//设置FIN_WAIT2定时器
5797                     } else if (th->fin || sock_owned_by_user(sk)) { //FIN与ACK同时设置或当前是进程上下文
5798                         /* Bad case. We could lose such FIN otherwise.
5799                          * It is not a big problem, but it looks confusing
5800                          * and not so rare event. We still can lose it now,
5801                          * if it spins in bh_lock_sock(), but it is really
5802                          * marginal case.
5803                          */
5804                         inet_csk_reset_keepalive_timer(sk, tmo);//设置FIN_WAIT2定时器
5805                     } else {
5806                         tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);//进入TCP_TIME_WAIT状态
5807                         goto discard;
5808                     }
5809                 }
5810             }
5811             break;
5812
5813         case TCP_CLOSING:
5814             if (tp->snd_una == tp->write_seq) { //FIN已经被确认
5815                 tcp_time_wait(sk, TCP_TIME_WAIT, 0);//进入TCP_TIME_WAIT状态
5816                 goto discard;
5817             }
5818             break;
5819
5820         case TCP_LAST_ACK:
5821             if (tp->snd_una == tp->write_seq) { //FIN已经被确认
5822                 tcp_update_metrics(sk);
5823                 tcp_done(sk);//彻底关闭连接
5824                 goto discard;
5825             }
5826             break;
5827         }
5828     }
...
5834     switch (sk->sk_state) {
5835     case TCP_CLOSE_WAIT:
5836     case TCP_CLOSING:
5837     case TCP_LAST_ACK:
5838         if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt))
5839             break;
5840     case TCP_FIN_WAIT1:
5841     case TCP_FIN_WAIT2:
5842         /* RFC 793 says to queue data in these states,
5843          * RFC 1122 says we MUST send a reset.
5844          * BSD 4.4 also does reset.
5845          */
5846         if (sk->sk_shutdown & RCV_SHUTDOWN) {//应用进程不想收包
5847             if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
5848                 after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) { //判断为真意味着有新数据到来
5849                 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
5850                 tcp_reset(sk);//发送RST
5851                 return 1;
5852             }
5853         }
5854         /* Fall through */
5855     case TCP_ESTABLISHED:
5856         tcp_data_queue(sk, skb);
5857         queued = 1;
5858         break;
5859     }
...
        收到ACK后,TCP会进行状态跳转:如果是TCP_FIN_WAIT1则跳转到TCP_FIN_WAIT2,这时还可以接收数据,称为“半关闭”;如果是TCP_LAST_ACK则直接关闭本端TCP连接;如果是TCP_LAST_ACK则进入TIME_WAIT状态;如果是在TCP_FIN_WAIT1状态下收到了FIN|ACK则先处理ACK标记(跳转到TCP_FIN_WAIT2),然后通过5841行代码调用tcp_data_queue处理FIN标记,在那里会进入TIME_WAIT状态。

你可能感兴趣的:(tcp,linux内核)