又被鹅厂搞懵了!

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 客户端(主动关闭方)在 TIME_WAIT 状态下,如果收到服务端的数据包时,会怎么处理?

大家好,我是小林。

昨天收到个读者的问题,他在面试鹅厂的时候,被面试官搞懵了,因为面试官问了他这么一个网络问题:

1.jpg

不得不说,鹅厂真的很喜欢问网络问题,而且爱问异常情况下的网络问题,之前也有篇另外一个读者面试鹅厂的网络问题:「被鹅厂面怕了!」」。我们来看看这位读者的问题,这个问题其实是在问:客户端(主动关闭方)在 TIME_WAIT 状态下,如果收到服务端的数据包时,会怎么处理?

2.jpg

这个问题迷惑性在于,客户端是使用了 shutdown 函数关闭了写方向,而读方向并没有关闭,也就是说客户端在挥手过程中,如果收到服务端的数据包,那么应用程序在调用 read 函数时,是可以读取到数据的。如果问题中的数据包没有被网络延迟,在第三次挥手之前被客户端收到了,那么客户端就可以在应用程序读取到该数据。所以疑惑就在于,数据包被延迟了,客户端在进入 TIME_WAIT 状态后,收到了服务端的数据包,应用程序还能读取到该数据吗?我先说结论吧,客户端进入 TIME_WAIT 状态后,如果收到了服务端的数据包,客户端的内核会发送该数据包的 ACK 确认报文,然后丢掉该数据包。

4.jpg


我为什么知道呢?因为我去看了下内核的源码,我在这里也带大家分析一遍。Linux 内核在收到 TCP 报文后,会执行 tcp_v4_rcv 函数,在该函数和 TIME_WAIT 状态相关的主要代码如下所示:image.gif该代码的过程:

3.jpg

  1. 接收到SKb包后,会调用__inet_lookup_skb()查找对应的sock结构;
  2. 如果连接的状态是 TIME_WAIT,会跳转到 do_time_wait 处理;
  3. 由 tcp_timewait_state_process() 函数来处理 SKB 包,处理后根据返回值来做相应的处理。

在看 tcp_timewait_state_process() 函数中的处理之前,需要先看一看不同的返回值会对应什么样的处理:

  • 如果返回值是 TCP_TW_SYN,则说明接收到的是一个「合法」的SYN包(也就是说这个 SYN 包可以接受),这时会首先查找内核中是否有对应的监听套接字,如果存在相应的监听套接字,则会释放TIME_WAIT状态的传输控制结构,跳转到 process 处开始处理,开始建立一个新的连接。如果没有找到监听套接字会执行到 TCP_TW_ACK 分支。
  • 如果返回值是TCP_TW_ACK,则会调用 tcp_v4_timewait_ack() 发送ACK,然后跳转到 discard_it,丢掉数据包。
  • 如果返回值是TCP_TW_RST,则会调用 tcp_v4_send_reset() 给对端发送 RST 包,然后丢掉数据包。
  • 如果返回值是TCP_TW_SUCCESS,则会直接丢掉数据包。

所以,关键的地方就在于,当连接在 TIME_WAIT 状态时,收到了 TCP 数据包,tcp_timewait_state_process() 函数的返回值是什么。tcp_timewait_state_process() 函数处理过程非常的多,我这里就不详细介绍里面的具体处理了,我这里直接说结论。主动关闭方在 TIME_WAIT 状态下,收到了 TCP 数据包的话,tcp_timewait_state_process() 函数会返回 TCP_TW_ACK,所以接下来会调用 tcp_v4_timewait_ack() 发送 ACK,然后跳转到 discard_it,丢掉数据包。可能有的同学会好奇,都要丢弃数据包了,为什么还要回 ACK?我觉得可能是避免对方因为没有收到数据包的确认报文,而触发超时重传包,毕竟已经在挥手的最末尾阶段了,就安安稳稳的结束吧。在 TIME_WAIT 状态下,还有个意思的事情是,当收到「合法」的 SYN 包,并且开启了 sysctl_tcp_tw_reuse 内核参数,就会直接释放掉 TIME_WAIT 的资源,然后进行新建连接的处理。


这次就说到这啦,下次见!

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
XML Java 程序员
跟面试官刚聊几句,被发现连这几道都不会,便被请了出去
跟面试官刚聊几句,被发现连这几道都不会,便被请了出去
76 0
编程要搞明白的东西(一)
编程要搞明白的东西(一)
85 0
|
6月前
|
存储 前端开发 数据可视化
刚关上灯准备睡时 女朋友抱着我说那个不明白 怎么办?
刚关上灯准备睡时 女朋友抱着我说那个不明白 怎么办?
|
Java
编程要搞明白的东西(二)
编程要搞明白的东西(二)
87 0
|
设计模式 运维 架构师
我懵了!架构描述是个啥玩意?
我懵了!架构描述是个啥玩意?
96 0
|
Android开发
ViewBingding?搞!
kotlin-android-extensions插件
204 0
ViewBingding?搞!
|
机器学习/深度学习 算法
一看就懂,一写就懵?搞懂回溯算法,一口气刷了20多道题(上)
回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。——摘自《百度百科》
214 0
一看就懂,一写就懵?搞懂回溯算法,一口气刷了20多道题(上)
|
算法
一看就懂,一写就懵?搞懂回溯算法,一口气刷了20多道题(中)
回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。——摘自《百度百科》
396 0
一看就懂,一写就懵?搞懂回溯算法,一口气刷了20多道题(中)
|
网络协议 Linux
被鹅厂搞懵逼了(更正)
在 FIN_WAIT_2 状态下如何处理乱序的 FIN 报文
被鹅厂搞懵逼了(更正)
|
Web App开发 搜索推荐 开发者
上了学这么久,我才知道他们为什么可以这么爽(上)
目录 前情提要 安装插件 1.下载链接 2.安装 遇到无法拖进去怎么办? 3.新的体验
上了学这么久,我才知道他们为什么可以这么爽(上)