💻 Computer Basics
1、计算机网络
1.1 传输层:TCP和UDP
1.1.1 三次握手
1.1.2 四次挥手
1.1.3 流量控制
1.1.4 拥塞控制
1.1.5 TCP和UDP的区别
1.1.6 TCP如何保证传输的可靠性
1.1.7 TCP长连接和短连接
1.1.8 应用层提高UDP协议可靠性的方法
1.1.9 UDP和IP的首部结构
1.2 应用层:HTTP和HTTPS
1.2.1 HTTP和HTTPS的区别
1.2.2 GET和POST的区别
1.2.3 Session与Cookie的区别
1.2.4 从输入网址到获得页面的过程(越详细越好)
1.2.5 HTTP请求有哪些常见的状态码
1.2.6 什么是RIP,算法是什么
1.2.7 HTTP1.1和HTTP2.0的主要区别
1.2.8 DNS
1.2.9 HTTPS加密和认证过程
1.2.10 常见网络攻击
1.2.11 REST
1.3 计算机网络体系结构
1.4 网络层协议
1.4.1 IP地址的分类
1.4.2 划分子网
1.4.3 什么是ARP协议
1.4.4 NAT协议
2、操作系统
2.1 进程和线程
2.1.1 进程和线程的区别
2.1.2 进程间通信方式
2.1.3 同步原语
2.1.4 进程状态
2.1.5 进程调度策略
2.1.6 僵尸进程和孤儿进程
2.1.7 协程
2.1.8 异常控制流
2.1.9 IO多路复用
2.1.10 用户态和内核态
2.2 死锁
2.3 内存管理
2.3.1 分段与分页
2.3.2 虚拟内存
2.3.3 页面置换算法
2.3.4 局部性原理
2.3.5 缓冲区溢出
2.4 磁盘调度
-
+
游客
注册
登录
四次挥手
## 1 什么是四次挥手 ![](/media/202206/2022-06-14_152459_744088.png) 1. **数据传输结束后**,**通信的双方都可释放连接**,现在 $A$ 和 $B$ 都处于 `ESTABLISHED`**状态**。 2. $A$**的应用进程先向其 TCP 发出连接释放报文段**,**并停止再发送数据**,**主动关闭 TCP 连接**,$A$**把连接释放报文段首部的终止控制位 $FIN$ 置 1**,**其序号 $seq = u$**,**他等于前面已传送过的数据的最后一个字节的序号加 1**,这时 $A$**进入 `FIN-WAIT-1`**(终止等待 1)**状态**,**等待 $B$ 的确认**,需要注意的是,**TCP 规定 $FIN$ 报文段即使不携带数据**,**他也要消耗掉一个序号**。 3. $B$**收到连接释放报文段后即发出确认**,**确认号是 $ack = u + 1$**,**而这个报文段自己的序号是 $v$**,**等于 $B$ 前面已传送过的数据的最后一个字节的序号加 1**,**然后 $B$ 就进入 `CLOSED-WAIT`**(关闭等待)**状态**,**TCP 服务器进程这时应通知高层应用进程**,**因而从 $A$ 到 $B$ 这个方向的连接就释放了**,**这时的 TCP 连接处于半关闭**(Half Close)**状态**,**即 $A$ 已经没有数据要发送了**,**但 $B$ 若发送数据**,$A$**仍要接收**,**也就是说**,**从 $B$ 到 $A$ 这个方向的连接并未关闭**,**这个状态可能会持续一段时间**。 4. $A$**收到来自 $B$ 的确认后**,**就进入 `FIN-WAIT-2`**(终止等待 2)**状态**,**等待 $B$ 发出的连接释放报文段**。 5. **若 $B$ 已经没有要向 $A$ 发送的数据**,**其应用进程就通知 TCP 释放连接**,**这时 $B$ 发出的连接释放报文段必须使 $FIN = 1$**,**现假定 $B$ 的序号为 $w$**(在半关闭状态 $B$ 可能又发送了一些数据),$B$**还必须重复上次已发送过的确认号 $ack = u + 1$**,**这时 $B$ 就进入 `LAST-ACK`**(最后确认)**状态**,**等待 $A$ 的确认**。 6. $A$**在收到 $B$ 的连接释放报文段后**,**必须对此发出确认**,**在确认报文段中把 $ACK$ 置 1**,**确认号 $ack = w + 1$**,**而自己的序号是 $seq = u + 1$**(**根据 TCP 标准**,**前面发送过的 $FIN$ 报文段要消耗一个序号**),**然后进入到 `TIME-WAIT`**(时间等待)**状态**,需要注意的是,**现在 TCP 连接还没有释放掉**,**必须经过时间等待计时器**(Time Wait Timer)**设置的时间 $ 2MSL $ 后**,$A$**才进入到** `CLOSED` **状态**,**才能开始建立下一个新的连接**,**当 $A$ 撤销相应的传输控制块后**,**就结束了这次的 TCP 连接**。 7. $B$**只要收到了$A$发出的确认**,**就进入 `CLOSED`状态**,**同样**,**$B$在撤销相应的传输控制块后**,**就结束了这次的TCP连接**,**我们注意到**,$B$**结束TCP连接的时间要比$A$早一些**。 > $MSL$ 叫做**最长报文段寿命**(Maximum Segment Lifetime),**RFC 793 建议设为 2 分钟**,**但这完全是从工程上来考虑的**,**对于现在的网络**,**2 分钟可能太长了一些**,**因此TCP允许不同的实现可根据具体情况使用更小的$MSL$值**,MSL是**任何报文在网络上存在的最长时间**,**超过这个时间的报文将被丢弃**。 > ## 2 CLOSE_WAIT ### 2.1 服务器端 CLOSE_WAIT 状态意义是什么(为什么不能把服务器发送的 ACK 和 FIN 合并起来,变成三次挥手) 1. 因为**服务器收到客户端断开连接的请求时,可能还有一些数据没有发完**,这时**先回复 `ACK`,表示接收到了断开连接的请求**。 2. **等到数据发完之后再发 `FIN`,断开服务器到客户端的数据传送**。 ### 2.2 TCP 挥手时出现大量 CLOSE_WAIT 怎么解决 1. 如果我们的服务器程序处于 CLOSE_WAIT 状态,说明 socket 是**被动关闭**的。 2. 这时候**服务器一直没有进行第三次挥手**,导致服务器**存在大量 CLOSE_WAIT 状态的连接**,大量这种情况发生**会影响服务器性能**,同样**可能导致套接字数量达到服务器上限**。 3. 导致这种情况的原因通常是**服务端发生异常后未关闭连接**,**或者 CLOSE_WAIT 的配置时间过长**,**如果是 MySQL**,**也可能存在事务开启后没有正确 `rollback` 或者 `commit` 的可能**。 4. 一般可以采用以下方法来进行排查: 1. `top`**查看 `cpu` 利用率和 `load` 情况**(**大量 CLOSE_WAIT 属于 IO 密集型**,会**导致 `load` 相比 `cpu` 利用率高出很多**)。 2. `netstat`**观察 `close_wait` 的数量变化**。 3. **`perf` 或者火焰图定位热点函数**。 ## 3 TIME_WAIT ### 3.1 客户端 TIME_WAIT 状态的意义是什么(为什么要等待 2MSL) 1. **为了保证$A$发送的最后一个$ACK$报文段能够到达$B$**: 1. **这个$ACK$报文段有可能丢失**,**因而使处在 `LAST-ACK`状态的$B$收不到对已发送的$FIN + ACK$报文段的确认**,**$B$会超时重传这个$FIN + ACK$报文段**,**而$A$就能在$ 2MSL $时间内收到这个重传的$FIN + ACK$报文段**,**接着$A$重传一次确认**,**重新启动$ 2MSL $计时器**,**最后**,$A$**和$B$都正常进入到 `CLOSED`状态**。 2. **如果$A$在 `TIME-WAIT`状态不等待一段时间**,**而是在发送完$ACK$报文段后立即释放连接**,**那么就无法按照正常步骤进入 `CLOSED`状态**。 2. **防止「已失效的连接请求报文段」出现在本连接中**: 1. $A$**在发送完最后一个$ACK$报文段后**,**再经过时间$ 2MSL $**,**就可以使本连接持续的时间内所产生的的所有报文段都从网络中消失**,**这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段**。 ### 3.2 TCP 挥手时出现大量 TIME_WAIT 怎么解决 1. **TIME_WAIT 是连接完全关闭前的最后一个状态**,**一个连接被关闭时**,**主动关闭的一端最后会进入 TIME_WAIT 状态**,**等待足够的时间以确保远程 TCP 接收到连接中断请求的确认**,**这个时间为 2MSL**。 2. 一般来说,当**系统有较大的并发短连接压力时**,都**会出现少量的 TIME_WAIT 连接**,这是正常的,但是有时候**系统上出现大量的 TIME_WAIT 状态的连接**,从而**导致再也没有可用端口来建立新的连接**。 3. 程序中产生大量 TIME_WAIT 状态的根本原因是**频繁创建断开 TCP 连接**,解决的基本思路是**把频繁创建的 TCP 短连接改成 TCP 长连接**。 4. 解决方法主要有以下几种: 1. **开启 TIME_WAIT 重用**: 1. **使用 TIME_WAIT 重用的时候需要保证下面任意一点**: 1. **初始序列号比 TIME_WAIT 老连接的末序列号大**。 2. 如果**使用了时间戳**,**新到来的连接的时间戳比老连接的时间戳大**。 2. 开启 TIME_WAIT 重用的方法为**在 `/etc/sysctl.conf` 中加入 `net.ipv4.tcp_tw_reuse = 1`**。 2. **将 TCP 短连接改造为长连接**: 1. 如果**发起连接的目标也是自己可控制的服务器**时,**他们自己的 TCP 连接通信最好采用长连接**,**避免大量 TCP 短连接每次建立**/**释放产生的各种开销**。 2. 如果**建立连接的目标是不受自己控制的机器**时,**能否使用长连接就需要考虑对方机器是否支持长连接方式了**。 ## 4 如果第二次挥手时服务器的 ACK 没有送达客户端,会怎样 1. 客户端没有收到 `ACK` 确认,会重新发送 `FIN` 请求。 ## 参考文献 1. [什么是四次挥手?](https://github.com/wolverinn/Waking-Up/blob/master/Computer%20Network.md#%E4%BB%80%E4%B9%88%E6%98%AF%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B) 2. [关于三次握手与四次挥手你要知道这些](https://mp.weixin.qq.com/s?__biz=MzUyNzgyNzAwNg==&mid=2247483765&idx=1&sn=70179fa0e28aacd42d4c15dbd08bc6fc)。 3. [close_wait 状态的产生原因及解决](https://mp.weixin.qq.com/s?src=11×tamp=1626837956&ver=3203&signature=PSehm2*n0yep5UMfCXKk-nQR2gVjRiiJp2hJiUim2bdO1gM3aJuPCruqE5j2P92p5BLBBo9JUdirnji89gX3DxjaZqFvTcgvbV1tEh4b5kWXqu02hVu1HxaOKRG4Q-CZ)。 4. [Socket 连接问题之大量 TIME_WAIT](https://zhuanlan.zhihu.com/p/52179877)。 5. [服务产生大量 TIME_WAIT 如何解决](https://www.jianshu.com/p/41f7e468f312)。 6. [time_wait 的快速回收和重用(转)](https://ivanzz1001.github.io/records/post/tcpip/2018/04/24/tcpip_timewait)。
ricear
2022年6月14日 17:58
©
BY-NC-ND(4.0)
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码