博客首页:热爱编程的大李子
文章目的:计算机网络之TCP 三次握手、四次挥手面试题分享
⛅️文章出处:小林 x 图解网络 ⛅️
博主在学习阶段,如若发现问题,请告知,非常感谢
同时也非常感谢各位小伙伴们的支持
每日一语:脚踏实地,勇往直前,你走过的路,每一步都算数!
感谢: 我只是站在巨人们的肩膀上整理本篇文章,感谢走在前路的大佬们!
最后,祝大家每天进步亿点点! 欢迎大家点赞➕收藏⭐️➕评论支持博主!
⭐️ ⭐️上篇文章-《我要进大厂》- 计算机网络夺命连环15问,你能坚持到第几问?(HTTP | HTTPS | HTTP演变) ⭐️ ⭐️
序列号:在建立连接时由计算机生成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送一次数据,就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。
确认应答号:指下一次「期望」收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决不丢包的问题。
控制位:
IP 层是 「不可靠」 的,它不保证网络包的交付、不保证网络包的按序交付、也不保证网络包中的数据的完整性
如果需要保障网络数据包的可靠性,那么就需要由上层(传输层)的 TCP 协议来负责。
因为 TCP 是一个工作在传输层的可靠数据传输的服务,它能确保接收端接收的网络包是无损坏、无间隔、非冗余和按序的。
TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。
面向连接:一定是 「一对一」进行连接,不能像 UDP 协议可以一个主机同时向多个主机发送消息,也就是一对多是无法做到的。
可靠的:无论的网络链路中出现了怎样的链路变化,TCP 都可以保证一个报文一定能够到达接收端;
字节流:消息是「没有边界」的,所以无论我们消息有多大都可以进行传输。并且消息是「有序的」,当
「前一个」消息没有收到的时候,即使它先收到了后面的字节,那么也不能扔给应用层去处理,同时「重复」的报文会自动丢弃。
简单来说就是,用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括Socket、序列号和窗口大小称为连接
所以我们可以知道,建立一个 TCP 连接是需要客户端与服务器端达成上述三个信息的共识。
TCP 四元组可以唯一的确定一个连接,四元组包括如下:
源地址
源端口
目的地址
目的端口
源地址和目的地址的字段(32位)是在 IP 头部中,作用是通过 IP 协议发送报文给对方主机。
源端口和目的端口的字段(16位)是在 TCP 头部中,作用是告诉 TCP 协议应该把报文发给哪个进程。
服务器通常固定在某个本地端口上监听,等待客户端的连接请求。
因此,客户端 IP 和 端口是可变的,其理论值计算公式如下:
对 IPv4,客户端的 IP 数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是服务端单机最
大 TCP 连接数,约为 2 的 48 次方。
UDP 不提供复杂的控制机制,利用 IP 提供面向「无连接」的通信服务
UDP 协议真的非常简,头部只有 8 个字节( 64 位),UDP 的头部格式如下:
1.连接
2.服务对象
3.可靠性
4.拥塞控制、流量控制
5.首部开销
6.传输方式
7.分片不同
由于 TCP 是面向连接,能保证数据的可靠性交付,因此经常用于:
由于 UDP 面向无连接,它可以随时发送数据,再加上UDP本身的处理既简单又高效,因此经常用于:
原因是 TCP 有可变⻓的「选项」字段,而 UDP 头部⻓度则是固定的(8个字节),无需多一个字段去记录 UDP 的首部⻓度。
先说说 TCP 是如何计算数据⻓度:
其中 IP 总⻓度 和 IP 首部⻓度,在 IP 首部格式是已知的。TCP 首部⻓度,则是在 TCP 首部格式已知的,所以就可以求得 TCP 数据的⻓度。
大家这时就奇怪了问:“ UDP 也是基于 IP 层的呀,那 UDP 的数据⻓度也可以通过这个公式计算呀? 为何还要有「包⻓度」呢?”
这么一问,确实感觉 UDP 「包⻓度」是冗余的。
因为为了网络设备硬件设计和处理方便,首部⻓度需要是 4 字节的整数倍。
如果去掉 UDP 「包⻓度」字段,那 UDP 首部⻓度就不是 4 字节的整数倍了,所以小林(本文的作者)觉得这可能是为了补全UDP 首部⻓度是 4 字节的整数倍,才补充了「包⻓度」字段。
TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手来进行的。
注:
关于三次握手更为详细的请见 小林的 图解HTTP
TCP 的连接状态查看,在 Linux 可以通过 netstat -napt
命令查看。
TCP 建立连接时,通过三次握手 能防止历史连接的建立,能减少双方不必要的资源开销,能帮助双方同步初始化序列号 。序列号能够保证数据包不重复、不丢弃和按序传输。
不使用「两次握手」和「四次握手」的原因:
具体细节请参考 小林的 图解HTTP
如果一个已经失效的连接被重用了,但是该旧连接的历史报文还残留在网络中,如果序列号相同,那么就无法分辨出该报文是不是历史报文,如果历史报文被新的连接接收了,则会产生数据错乱。
所以,每次建立连接前重新初始化一个序列号主要是为了通信双方能够根据序号将不属于本连接的报文段丢弃。
另一方面是为了安全性,防止黑客伪造的相同序列号的 TCP 报文被对方接收。
我们先来认识下 MTU 和 MSS
如果在 TCP 的整个报文(头部 + 数据)交给 IP 层进行分片,会有什么异常呢?
当 IP 层有一个超过 MTU 大小的数据(TCP 头部 + TCP 数据)要发送,那么 IP 层就要进行分片,把数据分片成若干片,保证每一个分片都小于 MTU。把一份 IP 数据报进行分片以后,由目标主机的 IP 层来进行重新组装后,再交给上一层 TCP 传输层。
这看起来井然有序,但这存在隐患的,那么当如果一个 IP 分片丢失,整个 IP 报文的所有分片都得重传。
因为 IP 层本身没有超时重传机制,它由传输层的 TCP 来负责超时和重传。
当接收方发现 TCP 报文(头部 + 数据)的某一片丢失后,则不会响应 ACK 给对方,那么发送方的 TCP 在超时
后,就会重发「整个 TCP 报文(头部 + 数据)」。
因此,可以得知由 IP 层进行分片传输,是非常没有效率的。
所以,为了达到最佳的传输效能 TCP 协议在建立连接的时候通常要协商双方的 MSS 值,当 TCP 层发现数据超过MSS 时,则就先会进行分片,当然由它形成的 IP 包的⻓度也就不会大于 MTU ,自然也就不用 IP 分片了。
经过 TCP 层分片后,如果一个 TCP 分片丢失后,进行重发时也是以 MSS 为单位,而不用重传所有的分片,大大增加了重传的效率。
SYN攻击
我们都知道 TCP 连接建立是需要三次握手,假设攻击者短时间伪造不同 IP 地址的 SYN 报文,服务端每接收到一个 SYN 报文,就进入 SYN_RCVD
状态,但服务端发送出去的 ACK + SYN
报文,无法得到未知 IP 主机的
ACK 应答,久而久之就会占满服务端的 SYN 接收队列(未连接队列),使得服务器不能为正常用户服务。
避免 SYN攻击方式一
修改 Linux 内核参数,控制队列大小和当队列满时应做什么处理
net.core.netdev_max_backlog
net.ipv4.tcp_max_syn_backlog
net.ipv4.tcp_abort_on_overflow
避免 SYN攻击方式二
天下没有不散的宴席,对于 TCP 连接也是这样, TCP 断开连接是通过四次挥手方式。
双方都可以主动断开连接,断开连接后主机中的「资源」将被释放
可以看到,每个方向都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手。
需要注意是:主动关闭连接的,才有 TIME_WAIT 状态。
从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN 一般都会分开发
送,从而比三次握手导致多了一次。
MSL 是 Maximum Segment Lifetime,报文最大生存时间,它是任何报文在网络上存在的最⻓时间,超过这个时间报文将被丢弃。为 TCP 报文基于是 IP 协议的,而 IP 头中有一个 TTL 字段,是 IP 数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同时发送 ICMP 报文通知源主机。
MSL 与 TTL 的区别: MSL 的单位是时间,而 TTL 是经过路由跳数。所以 MSL 应该要大于等于 TTL 消耗为 0 的时间,以确保报文已被自然消亡。
TIME_WAIT 等待 2 倍的 MSL,比较合理的解释是: 网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待 2 倍的时间。
比如如果被动关闭方没有收到断开连接的最后的 ACK 报文,就会触发超时重发 Fin 报文,另一方接收到 FIN 后,会重发 ACK 给被动关闭方, 一来一去正好 2 个 MSL。
2MSL 的时间是从客户端接收到 FIN 后发送 ACK 开始计时的。如果在 TIME-WAIT 时间内,因为客户端的 ACK
没有传输到服务端,客户端又接收到了服务端重发的 FIN 报文,那么 2MSL 时间将重新计时。
在 Linux 系统里 2MSL 默认是 60 秒,那么一个 MSL 也就是 30 秒。Linux 系统停留在 TIME_WAIT 的时
间为固定的 60 秒。
主动发起关闭连接的一方,才会有 TIME-WAIT 状态。
需要 TIME-WAIT 状态,主要是两个原因:
如果 TIME-WAIT 等待足够⻓的情况就会遇到两种情况:
所以客户端在 TIME-WAIT 状态等待 2MSL 时间后,就可以保证双方的连接都可以正常的关闭。
如果服务器有处于 TIME-WAIT 状态的 TCP,则说明是由服务器方主动发起的断开请求。
过多的 TIME-WAIT 状态主要的危害有两种:
第二个危害是会造成严重的后果的,要知道,端口资源也是有限的。如果发起连接一方的 TIME_WAIT 状态过多,占满了所有端口资源,则会导致无法创建新连接。
TCP 有一个机制是保活机制。这个机制的原理是这样的:
定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序。
OK,今天关于 计算机网络之 TCP 三次握手、四次挥手 面试题分享就到这里,希望本篇文章能够帮助到大家,同时也希望大家看后能学有所获!!!
好了,我们下期见~