文档章节

TCP 的三次握手,四次挥手和重要的细节—干货满满,建议细读

tobe的呓语
 tobe的呓语
发布于 2019/12/11 18:01
字数 2521
阅读 12.9K
收藏 189

最近把个人博客搭建好了,链接在这里:tobe的呓语,文章会先在博客和公众号更新~ 大家多多收藏啊

上一次讲了 UDP 协议,从这次开始,就要讲 TCP 协议了,因为 TCP 协议涉及到的东西很多,一篇文章概括不完,所以我把 TCP 协议的内容分成好几个部分,逐个击破。

TCP 报文段结构

一谈到 TCP 协议,大家最先想到的词就是「面向连接」和「可靠」。没错,TCP 协议的设计就是为了能够在客户端和服务器之间建立起一个可靠连接。

在讲连接过程之前,我们先来看看 TCP 的报文段结构,通过这个结构,我们可以知道 TCP 能够提供什么信息:

这里有几点是需要注意的:

  • TCP 协议需要一个四元组(源IP,源端口,目的IP,目的端口)来确定连接,这要和 UDP 协议区分开。多说一句,IP 地址位于 IP 报文段,TCP 报文段是不含 IP 地址信息的。
  • 基本 TCP 头部的长度是 20 字节,但是由于「选项」的长度是不确定的,所以需要「首部长度」字段明确给出头部长度。这里要注意的是,首部长度字段的单位是 32bit,也就是 4 字节,所以该字段的最小值是 5。
  • 标橙色的字段(确认序号,接收窗口大小,ECE,ACK)用于「回复」对方,举个例子,服务器收到对方的数据包后,不单独发一个数据包来回应,而是稍微等一下,把确认信息附在下一个发往客户端的数据帧上,也就是捎带技术。
  • 窗口大小是一个 16 位无符号数,也就是说窗口被限制在了 65535 字节,也就限制了 TCP 的吞吐量性能,这对一些高速以及高延迟的网络不太友好(可以想想为什么)。所幸 TCP 额外提供了窗口缩放(Window Scale)选项,允许对这个值进行缩放。

下面是 8 个标志位的含义,有的协议比较旧,可能没有前两个标志位:

标志位虽然很多,但是如果放到具体场景里来看的话,就很容易理解他们的作用了。

TCP 三次握手

三次握手就是为了在客户端和服务器间建立连接,这个过程并不复杂,但里面有很多细节需要注意。

这张图就是握手的过程,可以看到客户端与服务器之间一共传递了三次消息,这三次握手其实就是两台机器之间互相确认状态,我们来一点一点看。

第一次握手

首先是客户端发起连接,第一个数据包将 SYN 置位(也就是 SYN = 1),表明这个数据包是 SYN 报文段(也被称为段 1)。这一次发送的目的是告诉服务器,自己的初始序列号client_isn ,还有一个隐含的信息在图里没有表现出来,那就是告知服务端自己想连接的端口号。除了这些,客户端还会发送一些选项,不过这跟三次握手没多大关系,暂且按下不表。

段 1 里最需要注意的就是这个client_isn ,也就是初始序列号。「RFC0793^1」指出:

When new connections are created, an initial sequence number (ISN) generator is employed which selects a new 32 bit ISN. The generator is bound to a (possibly fictitious) 32 bit clock whose low order bit is incremented roughly every 4 microseconds. Thus, the ISN cycles approximately every 4.55 hours.

翻译过来就是,初始序列号是一个 32 位的(虚拟)计数器,而且这个计数器每 4 微秒加 1,也就是说,ISN 的值每 4.55 小时循环一次。这个举措是为了防止序列号重叠

但即使这样还是会有安全隐患——因为初始 ISN 仍然是可预测的,恶意程序可能会分析 ISN ,然后根据先前使用的 ISN 预测后续 TCP 连接的 ISN,然后进行攻击,一个著名的例子就是「The Mitnick attack^2」 。这里摘一段原文:

Mitnick sent SYN request to X-Terminal and received SYN/ACK response. Then he sent RESET response to keep the X-Terminal from being filled up. He repeated this for twenty times. He found there is a pattern between two successive TCP sequence numbers. It turned out that the numbers were not random at all. The latter number was greater than the previous one by 128000.

所以为了让初始序列号更难预测,现代系统常常使用半随机的方法选择初始序列号,详细的方法就不在这里展开了。

第二次握手

当服务器接收到客户端的连接请求后,就会向客户端发送 ACK 表示自己收到了连接请求,而且,服务器还得把自己的初始序列号告诉客户端,这其实是两个步骤,但是发送一个数据包就可以完成,用的就是前面说的捎带技术。图里的 ACK = client_isn + 1 是指确认号字段的值,要注意和 ACK 标志位区分开。

ACK 字段其实也有不少需要注意的点,不过这个跟滑动窗口一块讲比较直观,这里就先不提了。

这里重点强调一下,当一个 SYN 报文段到达的时候,服务器会检查处于 SYN_RCVD 状态的连接数目是否超过了 tcp_max_syn_backlog 这个参数,如果超过了,服务器就会拒绝连接。当然,这个也会被黑客所利用,「SYN Flood」就是个很好的例子。因为服务器在回复 SYN-ACK 后,会等待客户端的 ACK ,如果一定时间内没有收到,认为是丢包了,就重发 SYN-ACK,重复几次后才会断开这个连接,linux 可能要一分钟才会断开,所以攻击者如果制造一大批 SYN 请求而不回复,服务器的 SYN 队列很快就被耗尽,这一段时间里,正常的连接也会得不到响应。

服务器的这种状态称为静默(muted)。为了抵御 SYN Flood 攻击,服务器可以采用「SYN cookies」,这种思想是,当 SYN 到达时,并不直接为其分配内存,而是把这条连接的信息编码并保存在 SYN-ACK 报文段的序列号字段,如果客户端回复了,服务器再从 ACK 字段里解算出 SYN 报文的重要信息(有点黑魔法的感觉了),验证成功后才为该连接分配内存。这样,服务器不会响应攻击者的请求,正常连接则不会受到影响。

但 SYN cookies 本身有一些限制,并不适合作为默认选项,有兴趣可以自行 Google。

第三次握手

这是建立 TCP 连接的最后一步,经过前两次握手,客户端(服务器)已经知道对方的滑动窗口大小初始序列号等信息了,这不就完了吗?为什么还要第三次握手?

这是因为服务器虽然把数据包发出去了,但他还不知道客户端是否收到了这个包,所以服务器需要等待客户端返回一个 ACK,表明客户端收到了数据,至此,连接完成。

连接建立后,进入传输数据的阶段,这里就涉及到很多很多技术,我会另写文章。

四次挥手

有了三次握手的基础,四次挥手就比较容易理解了:

四次挥手的过程其实很简单,就是服务器和客户端互相发送 FIN 和 ACK 报文段,告知对方要断开连接。

四次挥手里值得关注的一点就是 TIME_WAIT 状态,也就是说主动关闭连接的一方,即使收到了对方的 FIN 报文,也还要等待 2MSL 的时间才会彻底关闭这条连接。(这里面的 MSL 指的是最大段生成期,指的是报文段在网络中被允许存在的最长时间。)可为什么不直接关闭连接呢

一个原因是,第四次挥手的 ACK 报文段不一定到达了服务器,为了不让服务器一直处于 LAST_ACK 状态(服务器会重发 FIN,直到收到 ACK),客户端还得等一会儿,看看是否需要重发。假如真的丢包了,服务器发送 FIN ,这个 FIN 报文到达客户端时不会超过 2MSL(一来一回最多 2MSL),这时候客户端这边的 TCP 还没关掉,还能重发 ACK。

另一个原因是,经过 2MSL 之后,网络中与该连接相关的包都已经消失了,不会干扰新连接。我们来看一个例子:假如客户端向服务器建立了新的连接旧连接中某些延迟的数据坚持到了新连接建立完毕,而且序列号刚好还在滑动窗口内,服务器就误把它当成新连接的数据包接收,如下图所示:

2MSL 机制就避免了这种情况。

关于 TIME_WAIT 还有很多有意思的地方,我觉得可以单独再写一篇文章了,这里就不再多说。

感觉写的有点乱了,因为 TCP 的知识确实是有点多,希望各位读者不要介意。

如果本文对你有帮助,欢迎关注我的公众号 tobe的呓语 ,带你深入计算机的世界~ 公众号后台回复关键词【计算机】有惊喜哦~

© 著作权归作者所有

tobe的呓语
粉丝 69
博文 15
码字总数 31884
作品 0
西安
私信 提问
加载中

评论(8)

开源中国首席酷炫拽
你的个人博客服务器是什么配置?
tobe的呓语
tobe的呓语 博主
阿里最低配的轻量应用服务器
蔡熙伟
蔡熙伟
现在成熟的web框架出现大量close_wait是问题?😎
开源中国首席罗纳尔多
开源中国首席罗纳尔多
您好,请问TCP的解析是系统做的工作吗?还有接收TCP的数据包怎么判断是都HTTP协议?
七合一的那只小金刚
七合一的那只小金刚
TCP包的解析是有socket系列函数完成的。至于tcp包内容解析例如HTTP协议,这就是应用自行解析的。例如HTTP Server的代码,都是自己封装HTTP协议,提供方法
水无月青云
水无月青云
那你可以安心睡了 楼主 无法用语言表达此刻心静
开源中国帅炸天
开源中国帅炸天
每次看TCP的文章都有不一样的感悟,不过想睡觉
tobe的呓语
tobe的呓语 博主
😂
【转】跟着动画来学习TCP三次握手和四次挥手

最近看到一篇很通俗易懂的描述TCP三次握手和四次挥手概念的文章,觉得特别好,怕以后找不到了,特意转载在这里学习一下。 原文地址:跟着动画来学习TCP三次握手和四次挥手 作者:老錢 链接:...

欧阳鹏
2018/07/16
0
0
TCP三次握手和四次挥手

哈喽!大家好,今天我们来共同认识一下什么是三次握手和四次挥手,来了解一下TCP客户端和服务器之间是如何进行通信的,又如何释放连接的呢? 其实,实际上三次握手就是指建立一个TCP连接时,...

MRUJ
2017/09/01
0
0
TCP三次握手和四次挥手全过程及为什么要三次握手解答

TCP三次握手和四次挥手的全过程 TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接: 位码即tcp标志位,有6种表示: SYN(synchronous建立连接) ACK(acknowl...

Tenderrain
2017/11/10
0
0
简析TCP的三次握手与四次挥手

TCP是什么? 具体的关于TCP是什么,我不打算详细的说了;当你看到这篇文章时,我想你也知道TCP的概念了,想要更深入的了解TCP的工作,我们就继续。它只是一个超级麻烦的协议,而它又是互联网...

sinat_36668731
2017/08/02
0
0
可靠的TCP连接为何是三次握手

首先,咱们先来熟悉下经典的tcp/ip模型。 tcp/ip 模型为了方便使用,将osi七层模型划分成了四层,分别为网络接口层,网络层,传输层,应用层。 他们作用分别为: 1)网络接口层:主要作用是将...

xiaoer_03
2018/06/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

在JavaScript中将数字转换为字符串的最佳方法是什么?

将数字转换为字符串的“最佳”方法是什么(就速度优势,清晰度优势,内存优势等而言)? 一些例子: String(n) n.toString() ""+n n+"" #1楼 如果需要将结果格式设置为特定的小数位数 (例如...

javail
22分钟前
111
0
51单片机中断学习

一、中断的概念 CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生); CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务); 待CPU将事件B处理完毕后,再回到原...

demyar
23分钟前
97
0
创龙TI KeyStone C66x多核定点/浮点DSP TMS320C665x 的拓展IO信号、FMC接口

广州创龙结合TI KeyStone系列多核架构TMS320C665x及Xilinx Artix-7系列FPGA设计的TL665xF-EasyEVM开发板是一款DSP+FPGA高速大数据采集处理平台,其底板采用沉金无铅工艺的6层板设计,适用于高...

Tronlong创龙
24分钟前
90
0
理解虚拟网络

概念 TUN/TAP,veth

认真即可
31分钟前
162
0
聊聊artemis的ServerConnectionLifeCycleListener

序 本文主要研究一下artemis的ServerConnectionLifeCycleListener BaseConnectionLifeCycleListener activemq-artemis-2.11.0/artemis-core-client/src/main/java/org/apache/activemq/artem......

go4it
31分钟前
111
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部