又被鹅厂问懵逼了:TCP 四次挥手收到乱序的 FIN 包会怎样处理?
代码
1346 人阅读
|
0 人回复
|
<
各人好,我是小林。
支到个读者的成绩,他正在面试鹅厂的时分,被弄懵了,由于面试民问了他那么一个收集成绩:
不能不道,鹅厂实的很喜好问收集成绩,并且爱问非常状况下的收集成绩,之前也有篇别的一个读者面试鹅厂的收集成绩:「被鹅厂里怕了!」。
不外那讲鹅厂的收集题多是发问的读者表述有成绩,由于假设 FIN 报文比数据包先到达客户端,此时 FIN 报文其实是一个治序的报文,此时客户真个 TCP 毗连其实不会从 FIN_WAIT_2 形态转换到 TIME_WAIT 形态。
因而,我们要存眷到面是看「正在 FIN_WAIT_2 形态下,是如何处理支到的治序到 FIN 报文,然后 TCP 毗连又是甚么时分才进进到 TIME_WAIT 形态?」。
我那里先间接道结论:
正在 FIN_WAIT_2 形态时,假设支到治序的 FIN 报文,那末便被会参与到「治序行列」,其实不会进进到 TIME_WAIT 形态。
等再次支到前里被收集提早的数据包时,会判定治序行列有无数据,然后会检测治序行列中能否有可用的数据,假设能正在治序行列中找到取当前报文的序列号连结的挨次的报文,便会看该报文能否有 FIN 标记,假设发明有 FIN 标记,这时候才会进进 TIME_WAIT 形态。
我也绘了一张图,各人能够分离着图去明白。
TCP 源码阐发
接下去,我带各人看看源码,听到要源码阐发,能够有的同窗便怂了。
其实要阐发我们今日那个成绩,只需懂 if else 就好了,我也会用中文去表述代码的逻辑,所以纯真看我的笔墨也是能够的。
此次我们重面阐发的是,正在 FIN_WAIT_2 形态下,支到 FIN 报文是如何处理的。
正在 Linux 内乱核里,当 IP 层处置完动静后,会经由过程回调 tcp_v4_rcv 函数将动静转给 TCP 层,所以那个函数便是 TCP 层支到动静的进口。
处于 FIN_WAIT_2 形态下的客户端,正在支到效劳真个报文后,终极会挪用 tcp_v4_do_rcv 函数。
接下去,tcp_v4_do_rcv 办法会挪用 tcp_rcv_state_process,正在那里会按照 TCP 形态做对应的处置,那里我们只存眷 FIN_WAIT_2 形态。
正在上里那个代码里,能够看到假设 shutdown 封闭了读标的目的,那末正在支到对圆收去的数据包,则会再起 RST 报文。
而我们此次的标题问题里, shutdown 只封闭了写标的目的,所以会持续往下挪用 tcp_data_queue 函数(由于 case TCP_FIN_WAIT2 代码块里并出有 break 语句,所以会走到该函数)。
正在上里的 tcp_data_queue 函数里,假设支到的报文的序列号是我们预期的,也便是有序的话:
- 会判定该报文有无 FIN 标记,假设有的话便会挪用 tcp_fin 函数,那个函数卖力将 FIN_WAIT_2 形态转换为 TIME_WAIT。
- 接着借会看治序行列有无数据,假设有的话会挪用 tcp_ofo_queue 函数,那个函数卖力检查治序行列中能否无数据包可用,即能不克不及正在治序行列找到取当前数据包连结序列号连续的数据包。
而当支到的报文的序列号没有是我们预期的,也便是治序的话,则挪用 tcp_data_queue_ofo 函数,将报文参与到治序行列,那个行列的数据构造是白乌树。
我们的标题问题里,客户端支到的 FIN 报文实践上是一个治序的报文,因而此时其实不会挪用 tcp_fin 函数停止形态转换,而是将报文经由过程 tcp_data_queue_ofo 函数参与到治序行列。
然后当客户端支到被收集提早的数据包后,此时由于该数据包的序列号是希冀的,然后又由于上一次支到的治序 FIN 报文被参与到了治序行列,表白治序行列是无数据的,因而便会挪用 tcp_ofo_queue 函数。
我们去看看 tcp_ofo_queue 函数。
正在上里的 tcp_ofo_queue 函数里,正在治序行列中找到能取当前报文的序列号连结的挨次的报文后,会看该报文能否有 FIN 标记,假设有的话,便会挪用 tcp_fin() 函数。
最初,我们去看看 tcp_fin 函数的处置。
能够看到,假设当前的 TCP 形态为 TCP_FIN_WAIT2,便会收收第四次挥脚 ack,然后挪用 tcp_time_wait 函数,那个函数里会将 TCP 形态变动为 TIME_WAIT,并启动 TIME_WAIT 的按时器。
怎样看 TCP 源码?
之前有很多同窗问我,我是怎样看 TCP 源码的?
其实我看 TCP 源码,并非间接翻开 Linux 源码间接看,由于 Linux 源码其实太宏大了,假设我没有明白 TCP 进口函数正在哪,那几乎便是年夜海捞针。
所以,正在看 TCP 源码,我们能够来网上搜刮下他人的源码阐发,网上曾经有许多先辈帮我们阐发了 TCP 源码了,并且各个函数的挪用链路,他们皆有写出去了。
好比,您念理解 TCP 三次握脚/四次挥脚的源码完成,您就能够以「TCP 三次握脚/四次挥脚的源码阐发」如许枢纽字去搜刮,年夜部门文章的正文写的仍是很明晰,我最开端便按这类方法去进修 TCP 源码的。
网上的文章普通只会将重面的部门,许多代码细节出有揭出去,假设您念完好的看到函数的局部代码,那便得看内乱核代码了。
那里保举个看 Linux 内乱核代码的正在线网站:
https://elixir.bootlin.com/linux/latest/source
我以为仍是挺好用的,左边各个版本的代码皆有,左上角也能够搜刮函数。
所以,我看 TCP 源码的经历便是,先正在网上找找先辈写的 TCP 源码阐发,然后明白全部函数的挪用链路后,假设念具体理解某个函数的具体完成,能够正在我道的那个看 Linux 内乱核代码的正在线网站上搜刮该函数,就能够看到完好的函数的完成。假设半途碰到看没有懂的代码,也能够将那个代码复造到百度大要谷歌搜刮,普通也能找到他人阐发的历程。
教会了看 TCP 源码其实有助于我们阐发一些非常成绩,便好比今日那讲收集标题问题,正在网上其实是搜刮没有出谜底的,并且我们也很易用尝试的方法去模仿。
所以要念明白谜底,只能来看源码。
此次便道到那啦,我们下次睹!
免责声明:假如进犯了您的权益,请联络站少,我们会实时删除侵权内乱容,感谢协作! |
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,按照目前互联网开放的原则,我们将在不通知作者的情况下,转载文章;如果原文明确注明“禁止转载”,我们一定不会转载。如果我们转载的文章不符合作者的版权声明或者作者不想让我们转载您的文章的话,请您发送邮箱:Cdnjson@163.com提供相关证明,我们将积极配合您!
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。
|
|
|
|
|