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,应用进程还是能够知道发生了连接关闭事件。
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状态。