---
title: 《BAT高频面点》计算机网络高频面试题八股文（必看👍）
category: 
  - Java
  - 计算机网络
tag:
  - Java基础
head:
  - - meta
    - name: keywords
      content: HTTP,TCP,UDP,IP,网络,三次握手,四次挥手
    - name: description
      content: 图解《计算机网络-BAT高频面题》全网质量最高计算机网络常见知识点和面试题总结，希望对你有帮助
---

## 网络体系
### 1、说下计算机网络体系结构

计算机网络体系结构，一般有三种：OSI 七层模型、TCP/IP 四层模型、五层结构。

![image-20230528212420563](https://xiaolongcoder.oss-cn-beijing.aliyuncs.com/imgs/Java2Top/java202305282124759.png)

而OSI 是一个理论上的网络通信模型，TCP/IP 是实际上的网络通信模型，五层结构就是为了介绍网络原理而折中的网络通信模型。

::: info

重点理解记忆 TCP/IP 四层模型

:::

![image-20230409124229318](https://xiaolongcoder.oss-cn-beijing.aliyuncs.com/imgs/Java2Top/java/k202304091242759.png)

TCP/IP 网络通常是由上到下分成 4 层，分别是**应用层，传输层，网络层和网络接口层**。而网络接口层的传输单位是帧（frame），IP 层的传输单位是包（packet），TCP 层的传输单位是段（segment），HTTP 的传输单位则是消息或报文（message）。统称为数据包。

### 2、浏览器地址栏键入网址 URL 到显示网页的过程？

### 3、域名 DNS 解析过程？

DNS，英文全称是 **domain name system**，域名解析系统，它的作用也很明确，就是域名和 IP 相互映射。

DNS 的解析过程如下图：

假设你要查询 **[www.baidu.com](http://www.baidu.com/)** 的 IP 地址:

- 首先会查找浏览器的缓存,看看是否能找到**[www.baidu.com](http://www.baidu.com/)** 对应的 IP 地址，找到就直接返回；否则进行下一步;
- 查询本机系统 `HOSTS` 文件，找到就直接返回；否则进行下一步;
- 将请求发往给本地 DNS 服务器，如果查找到也直接返回，否则继续进行下一步；

- 本地 DNS 服务器向**根域名服务器**发送请求，根域名服务器返回负责`com`的顶级域名服务器的 IP 地址的列表。
- 本地 DNS 服务器再向其中一个负责`com`的顶级域名服务器发送一个请求，返回负责`baidu.com`的权限域名服务器的 IP 地址列表。
- 本地 DNS 服务器再向其中一个权限域名服务器发送一个请求，返回**[www.baidu.comopen in new window](http://www.baidu.com/)**所对应的 IP 地址

> 客户端——》本地域名服务器（递归查询）
>
> 本地域名服务器——》DNS服务器的交互查询是迭代查询

## HTTP

### 1、说说 HTTP 常用的状态码及其含义？

HTTP 状态码首先应该知道个大概的分类：

- 1XX：信息性状态码
- 2XX：成功状态码
- 3XX：重定向状态码
- 4XX：客户端错误状态码
- 5XX：服务端错误状态码

**记住面试常考的即可：**

![image-20230409134623333](https://xiaolongcoder.oss-cn-beijing.aliyuncs.com/imgs/Java2Top/java/k202304091346430.png)

> **说一下 301 和 302 的区别？**

- 301：永久性移动，请求的资源已被永久移动到新位置。服务器返回此响应时，会返回新的资源地址。
- 302：临时性性移动，服务器从另外的地址响应资源，但是客户端还应该使用这个地址。

### 2、HTTP 有哪些请求方式？哪些是幂等的？Resultful风格方法有哪些？

3、说⼀下 GET 和 POST 的区别？

### 3、说一下 HTTP 的报文结构

HTTP 报文有两种，HTTP 请求报文和 HTTP 响应报文：

- **请求**：请求行（请求方法+ `HTTP` 版本+ `URL` 地址）、请求头（key-value 键值对）、空格、请求体

- **响应**：状态行（状态码+状态值+ `HTTP` 版本）、响应头（key-value 键值对）、空格、响应头

**HTTP 常见请求头**：

- `Connection`: keep-alive（开启长连接）
- `User-Agent`（客户端使用的操作系统和浏览器的名称和版本）
- `Accept`：text/html（浏览器可接受类型）
- `Accept-Language`、`Host` (被请求资源的Internet主机和端口号)

### 4、HTTP 请求的过程与原理？

HTTP 协议定义了浏览器怎么向服务器请求文档，以及服务器怎么把文档传给浏览器。

![image-20230528212620909](https://xiaolongcoder.oss-cn-beijing.aliyuncs.com/imgs/Java2Top/java202305282126142.png)

- 每个服务器都有一个进程，它不断监听 TCP 的端口 80，以便发现是否有浏览器向它发出连接建立请求
- 监听到连接请求，就会建立 TCP 连接
- 浏览器向服务器发出浏览某个页面的请求，服务器接着就返回所请求的页面作为响应
- 最后，释放 TCP 连接

> 详细展开说，即 ”键入网址，到回显网页其中发生了什么？“

### 5、说下 HTTP/1.0，1.1，2.0 的区别？

关键需要记住 **HTTP/1.0** 默认是短连接，可以强制开启，HTTP/1.1 默认长连接，HTTP/2.0 采用**多路复用**。

**HTTP/1.0**

- 默认使用**短连接**，每次请求都需要建立一个 TCP 连接。它可以设置`Connection: keep-alive` 这个字段，强制开启长连接。

**HTTP/1.1**

1. **支持断点续传**，对带宽进行了优化，不用每次只要对象一部分而把整个对象传过来（分块传输）支持长连接。
2. **流水线**（piping管道传输），使得一次TCP连接可以多次HTTP通信，并且可以使得发起一次HTTP请求后不用等响应就可以继续发下一次（虚假并行）。
3. 将客户端的队列传输移到了服务端，服务端需要队列顺序处理请求返回，这样就可能造成队头阻塞，HTTP2.0采用多路复用解决了
4. **引入了更多的状态码**，比如206断点传输返回；100，使得不用每次请求都发body，可以先试探的发一个header，看是否有权限，若有返回100，下一次发带body的请求，没有权限返回401.
5. 引入了更多的缓存策略，如if-match
6. 默认开启**长连接**keep-alive，增加HOST域（一台服务器多个虚拟主机）

**缺点**：

1、没有头部压缩，服务器端按队列顺序处理请求

2、队头阻塞（多路复用）

3、服务器只能被动响应，2.x 引入 `主动推送`

**HTTP/2.0**

- **头部压缩**：（2之前 body 有对应压缩算法，但是 header 没有，header 里面有大量固定字段，如 `Accept cookie` 等，大量请求下，会有很多冗余字段，2引入 `Hpack 压缩算法` 对头部进行压缩）
- **多路复用**：（由于1.0 虽然也引入了流水线 长连接 提高了效率，但是服务端只能按队列顺序处理请求返回，会造成对头阻塞）2.0引入**二进制帧**，**stream流**：一个 `TCP` 连接里面可以有多个 `Stream` 流，请求可以再各自 `Stream` 里面并发执行，`Stream` 里面请求响应消息由一个个帧组成，带有 `stream id`，所以不同 `stream` 里面帧可以乱序发送，接收端可以根据 `streamid` 按序拼接。
- **服务器推送**：比如请求 `html`，会直接把你需要的 `js css img` 传给你 不用自己再去请求一次（可以通过 nginx 配置）

**HTTP/3**

HTTP/3 主要有两大变化，**传输层基于 UDP**、使用**QUIC 保证 UDP 可靠性**。

HTTP/2 存在的一些问题，比如重传等等，都是由于 TCP 本身的特性导致的，所以 HTTP/3 在 QUIC 的基础上进行发展而来，QUIC（Quick UDP Connections）直译为快速 UDP 网络连接，底层使用 UDP 进行数据传输。

**HTTP/3 主要有这些特点**：

- 使用 UDP 作为传输层进行通信
- 在 UDP 的基础上 QUIC 协议保证了 HTTP/3 的安全性，在传输的过程中就完成了 TLS 加密握手
- HTTPS 要建⽴⼀个连接，要花费 6 次交互，先是建⽴三次握⼿，然后是 TLS/1.3 的三次握⼿。QUIC 直接把以往的 TCP 和 TLS/1.3 的 6 次交互合并成了 **3** 次，减少了交互次数。
- QUIC 有⾃⼰的⼀套机制可以保证传输的可靠性的。当某个流发⽣丢包时，只会阻塞这个流，其他流不会受到影响。

我们拿一张图看一下 HTTP 协议的变迁：

![Http协议变迁](https://xiaolongcoder.oss-cn-beijing.aliyuncs.com/imgs/Java2Top/java202305282126968.png)

### 6、 HTTP 与 HTTPS 的区别？  

- `HTTP` 不安全，明文传输，端口 80，地址 `Http://`，运行在 `TCP` 之上。
- `HTTPS` 安全，混合加密传输，端口443，地址 `Https://`，相当于是身披 SSL 的 HTTP，**HTTPS** 运行于 **SSL** 之上，**SSL** 运行于 **TCP** 之上。
- `HTTPS` 比 `HTTP` 更安全，但是由于加密解密更耗资源。
- `HTTPS` 混合加密机制：**内容**传输使用**对称加密**，但**对称加密的密钥**使用服务端的证书进行了**非对称加密**。

### 7、HTTPS 的连接过程?

这道题有几个要点：**公私钥、数字证书、加密、对称加密、非对称加密**。

**HTTPS 主要工作流程：**

- 客户端发起 `HTTPS` 请求，携带 `随机数+支持的加密算法+支持的SSL版本` 等信息致服务端
- 服务端选择 `协议版本，加密算法`，然后和 `证书与随机数 `发给客户端
- 客户端验证CA证书合法性（CA公钥事先已经置于浏览器或操作系统）
- 客户端产生随机数（**预主密匙**）并用 **证书公钥** 加密发给服务端
- 客户端告知服务端**将使用加密通信**，用协商的加密算法与通信密匙（`通信密匙=客户端随机数+服务端随机数+预主密匙`）
- 客服端发送消息给服务端，让其**验证客服端**是不是刚才建立信任的客户端（之前全部发送的内容做个摘要）
- 服务端收到加密后的 **预主密匙** 用 **CA私钥** 解密，再结合它的随机数与客户端随机数生成 **通信密匙**（与客户端算法一致，见上）
- 服务端验证客户端发来验证消息，无误告知客户端使用加密通信，也向客户端发送验证消息
- 客户端验证服务端发来的消息，
- 无误后，之后开始使用 `通信密匙` 加密通信

![https 主要流程](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/weixin-mianznxjsjwllsewswztwxxssc-d91b220e-a7e0-4856-af53-697c96591ec7.jpg)

> 服务端有一套数字证书（证书内容有公钥、证书颁发机构、失效日期等）

### 8、 对称加密算法与非对称加密算法？  

**对称加密**：使用同一把密钥进行加密解密，运算速度快，安全性较低

**非对称加密**：使用公钥对传输数据加密，再使用密钥对数据解密，运算速度慢，更耗资源，安全性更高

## TCP

### 1、详细说一下 TCP 的三次握手机制？

开始客户端服务端都处于CLOSE状态，然后服务端主动监听某个端口，处于listen状态

**客户端发送SYN报文**：客户端随机初始化seq=x，并将序列号置于TCP首部序列号字段中，并将SYN标志位置为1，发送SYN报文到服务端，客户端变为SYN_SEND

**服务端发送SYN+ACK报文**：服务端收到客户端的SYN报文，也会随机初始化序列号seq=y，并将序列号置于TCP首部序列号字段，还会将x+1置于确认应答号字段中，然后置SYN=1,ACK=1将报文发给客户端，不包含应用层数据，之后服务端处于SYN_REVD状态

**客户端发送ACK报文：**客户端收到服务端报文，向服务端发送确认的确认，置ACK标志位为1，确认应答号为y+1，然后发给服务端，这次可以携带数据，此后，客户端服务端都处于ESTABLISHED状态。

------

客户端发起连接请求报文段（客：SYBN_SEND）

服务端为该TCP连接分配缓存与变量，给予确认（服：SYN_REVD）

客户端为该TCP连接分配缓存与变量（客：ESTABLISHED）,给予确认的确认（服：ESTABLISHED）

### 2、为什么三次握手？  

**三次握⼿才可以阻⽌历史连接的重复初始化**（主要原因）：由于某些原因当旧的连接比新的连接先到达服务端，服务端回发一个SYN+ACK报文，客户端收到后与自己**上下文比对（序列号**），发现这是历史连接（序列号过期或超时），便会发送**RST报文**到服务端终止这次连接。**如果是历史连接（序列号过期或超时），则第三次握⼿发送的报⽂是 RST 报⽂，以此中⽌历史连接，而两次握手不行**。

**同步双方序列号**：TCP通信双方，需维护序列号来保证可靠传输（数据去重，有序等），客户端发送初始化序列号给服务端，服务端收到也要发一个给客户端，客户端收到也要对服务端回复一个确认，两次握手只能保证一方初始化序列能被接收，不能保证两方都可，不可靠

**数据传输可靠性**：服务端接收客户端数据给出确认，代表服务端有接收数据与发送数据能力，不知道客户端有没有接收数据能力，数据不可靠。

**防止资源浪费**：某个连接请求因网络延迟，延至到下一个请求正常连接释放后到达服务端，服务端给出确认，如果两次握手代表连接建立，但是客户端此时不会理会这个延迟请求了，服务端就一致超时重传，浪费资源。也可能客户端的 SYN 阻塞了，重复发送多次 SYN 报⽂，只有两次握手客户端收到报文不会给出确认，那么服务端不知道客户端收到自己发的报文没，那么服务器在收到请求后就会建⽴多个冗余的⽆效链接，造成不必要的资源浪费

### 3、TCP四次挥手？  

客服端发起连接释放报文，TCP首部FIN字段置为1，发送FIN报文（客：FIN_WAITE1）

服务端接收并回传一个确认报文段,ACK=1（服：CLOSE_WAITE 客：FIN_WAITE2）

服务端处理完发起连接释放报文，置FIN=1，TCP主动关闭（服：LAST_ACK）

客户端收到FIN报文，给予回复ACK报文（客：TIME_WAITE）

服务端收到ACK报文，进入CLOSED状态,服务端完成连接释放

客户端等2MSL后，进入CLOSED状态，客户端完成连接释放

**服务器端在发送完FIN后还能收到数据吗**？

当收到对方的FIN报文时, 仅仅表示对方不在发送数据了, 但是还能接收数据  不发数据，可以接收数据

### 4、为什么四次挥手？

客户端释放连接，但是此时服务端可能还有数据要处理，先暂且给客户端一个回复确认，等处理完后在释放连接，所以要四次

被动方此时有可能还有相应的数据报文需要发送

### 5、为什么要等2MSL（最长报文连接）才彻底释放连接？为什么要Time_wait状态？  

首先知道**MSL**意思（**最长报文存活时间**）

- 防止最后一个ACK被动关闭方没收到，那么被动关闭方可以超时重传，这样一来一回最长就2MSL
- 防止旧连接数据包到达，经过2MSL足够让旧连接报文过期消失

![2MSL 恰好一个来回](https://xiaolongcoder.oss-cn-beijing.aliyuncs.com/imgs/Java2Top/java202305282133509.png)

### 6、Time_wait 过多有什么危害？  

内存资源占用、端口资源占用（一个TCP连接至少消耗一个端口），每端口，无法建立新连接。

服务器资源受限：服务器监听一个端口，会把连接丢给线程处理，可以继续监听端口，但是线程池处理不了那么多连接。

### 7、Time_wait 状态过多的优化？  

（这其实和下面38是同一个问题）

**什么时候产生**：首先调用close()发起主动关闭的一方，再发送最后一个ACK之后

**为何产生**：确保最后一个ACK到达，保证TCP全双工连接可靠释放；使旧的数据包过期消失。

什么时候会产生大量Time_wait：当**请求量比较大**的时候，**而且所有的请求都是短连接的时候**

**如何避免**：多IP增加随机端口；内核参数调优（服务器设置SO_REUSEADDR套接字选项来通知内核，如果端口忙，但TCP连接位于TIME_WAIT状态时可以重用端口）；使用长连接（Connection：keep-alive）、Linux参数net.ipv4.tcp_tw_reuse 和 tcp_timestamps开启，复⽤处于 TIME_WAIT 的 socket 为新的连接所⽤

### 8、TCP 怎样保证可靠传输的？  

校验和、确认应答、序列和、超时重传、流量控制、拥塞控制

### 9、DNS 使用什么协议？  

53 端口；DNS 服务器间进行域传输的时候用 TCP 53（域名服务器之间进行数据同步，保证数据一致性，要求可靠）；客户端查询DNS服务器时用 UDP 53，DNS查询超过 512字节，TCP 标志出现 使用 TCP 发送。

### 10、半连接队列与全连接队列？  

**长连接**：一次 TCP 连接，多次 HTTP 通信

**短连接**：一次连接，一次通信

### 11、SYN攻击？

SYN 攻击，就是伪造大量虚假 IP 发起连接，请求，服务端返回 SYN+ACK 报文，由于 IP 虚假不会给服务端确认应答，一直便处于半连接状态置于半连接队列，等队列占满，无法给正常连接服务。

### 12、TCP 的粘包问题怎么解决？

#### 粘包产生的原因：

1. **发送的数据**小于 TCP 发送缓冲区的大小。
2. TCP 将多次写入缓冲区的数据一次发送出去，将会发送粘包；
3. 接收数据端的应用层没有及时读取接收缓冲区中的数据，将发生粘包。
4. 要发送的数据大于 TCP 缓冲区剩余空间的大小，将发生拆包。

**解决方法：**使用带**消息头的协议**，消息头存储消息开始标志及消息长度；**消息定长**，每次发送固定长度消息；设置**消息边界**，界限符分割；更复杂的应用层协议

![image-20230528214421388](https://xiaolongcoder.oss-cn-beijing.aliyuncs.com/imgs/Java2Top/java202305282144544.png)

### 13、Time_wait什么时候·产生？为何产生？怎样避免？  

**什么时候产生**：首先调用close()发起主动关闭的一方，再发送最后一个ACK之后

**为何产生**：确保最后一个ACK到达，保证TCP全双工连接可靠释放；使旧的数据包过期消失。

**什么时候会产生大量Time_wait**：当**请求量比较大**的时候，**而且所有的请求都是短连接的时候**

**如何避免**：多IP增加随机端口；内核参数调优（服务器设置SO_REUSEADDR 套接字选项来通知内核，如果端口忙，但TCP连接位于TIME_WAIT状态时可以重用端口）；使用长连接（Connection：keep-alive）、Linux 参数 net.ipv4.tcp_tw_reuse 和 tcp_timestamps 开启，复⽤处于 TIME_WAIT 的 socket 为新的连接所⽤

### 14、说说 TCP 报文首部的格式？

### 15、TCP与UDP区别及场景？（首部格式、大小、场景）  

TCP **可靠传输**，面向**字节流**，拥塞控制，流量控制，一对一

UDP 不可靠传输，面向报文，没有拥塞控制，流量控制，支持一对一，一对多

TCP 首部长度若没有选项字段大小 20 字节，UDP 首部长度固定 8 字节（这也是为何udp没有首部长度字段）

###### 使用场景：

TCP 效率要求低，准确性要求高的（文件传输）；UDP 效率要求高，准备要求相对可以低点（QQ聊天，视频通话）

###### 为何udp快：

不需要建立连接、没有超时重传、对收到数据不需给确认、没有流量控制拥塞控制

###### TCP 首部格式：

20字节源端口、目的端口、序列号、确认号、数据偏移、保留字、URG、ACK、FIN、PSH、FIN

###### UDP 首部格式：

首部 8 字节，源端口、目的端口、包长度、检验和，再计算检验和时还会添加 12 字节的伪首部

### 16、TCP 是如何保证可靠性的？

TCP 主要提供了检验和、序列号/确认应答、超时重传、最大消息长度、滑动窗口控制等方法实现了可靠性传输。

(详情待补充。。)

### 17、说说 TCP 的流量控制？

### 18、详细说说 TCP 的滑动窗口？

### 19、说说 TCP 的拥塞控制？

### 20、说说 TCP 的重传机制？

## UDP

### 1.UDP 协议为什么不可靠？

UDP 在传输数据之前不需要先建立连接，远地主机的运输层在接收到 UDP 报文后，不需要确认，提供不可靠交付。总结就以下四点：

- 不保证消息交付：不确认，不重传，无超时
- 不保证交付顺序：不设置包序号，不重排，不会发生队首阻塞
- 不跟踪连接状态：不必建立连接或重启状态机
- 不进行拥塞控制：不内置客户端或网络反馈机制

### [#](https://tobebetterjavaer.com/sidebar/sanfene/network.html#_47-dns-为什么要用-udp)2.DNS 为什么要用 UDP?

更准确地说，DNS 既使用 TCP 又使用 UDP。

当进行区域传送（主域名服务器向辅助域名服务器传送变化的那部分数据）时会使用 TCP，因为数据同步传送的数据量比一个请求和应答的数据量要多，而 TCP 允许的报文长度更长，因此为了保证数据的正确性，会使用基于可靠连接的 TCP。

当客户端想 DNS 服务器查询域名（域名解析）的时候，一般返回的内容不会超过 UDP 报文的最大长度，即 512 字节，用 UDP 传输时，不需要创建连接，从而大大提高了响应速度，但这要求域名解析服务器和域名服务器都必须自己处理超时和重传从而保证可靠性。

## IP

### 1、IP 地址有哪些分类？

一个 IP 地址在这鞥个互联网范围内是惟一的，一般可以这么认为，IP 地址 = {<网络号>，<主机号>}。

1. **网络号**：它标志主机所连接的网络地址表示属于互联网的哪一个网络。
2. **主机号**：它标志主机地址表示其属于该网络中的哪一台主机。

IP 地址分为 A，B，C，D，E 五大类：

- A 类地址 (1~126)：以 0 开头，网络号占前 8 位，主机号占后面 24 位。
- B 类地址 (128~191)：以 10 开头，网络号占前 16 位，主机号占后面 16 位。
- C 类地址 (192~223)：以 110 开头，网络号占前 24 位，主机号占后面 8 位。
- D 类地址 (224~239)：以 1110 开头，保留为多播地址。
- E 类地址 (240~255)：以 1111 开头，保留位为将来使用

![IP 地址分类](https://xiaolongcoder.oss-cn-beijing.aliyuncs.com/imgs/Java2Top/java202305282146607.png)

ping，**Packet Internet Groper**，是一种因特网包探索器，用于测试网络连接量的程序。Ping 是工作在 TCP/IP 网络体系结构中应用层的一个服务命令， 主要是向特定的目的主机发送 ICMP（Internet Control Message Protocol 因特网报文控制协议） 请求报文，测试目的站是否可达及了解其有关状态。

![Ping百度](https://xiaolongcoder.oss-cn-beijing.aliyuncs.com/imgs/Java2Top/java202305282149349.png)

一般来说，ping 可以用来检测网络通不通。它是基于`ICMP`协议工作的。假设**机器 A** ping **机器 B**，工作过程如下：

1. ping 通知系统，新建一个固定格式的 ICMP 请求数据包
2. ICMP 协议，将该数据包和目标机器 B 的 IP 地址打包，一起转交给 IP 协议层
3. IP 层协议将本机 IP 地址为源地址，机器 B 的 IP 地址为目标地址，加上一些其他的控制信息，构建一个 IP 数据包
4. 先获取目标机器 B 的 MAC 地址。
5. 数据链路层构建一个数据帧，目的地址是 IP 层传过来的 **MAC 地址**，源地址是本机的 **MAC 地址**
6. 机器 B 收到后，对比目标地址，和自己本机的 MAC 地址是否一致，符合就处理返回，不符合就丢弃。
7. 根据目的主机返回的 ICMP 回送回答报文中的时间戳，从而计算出往返时间
8. 最终显示结果有这几项：发送到目的主机的 IP 地址、发送 & 收到 & 丢失的分组数、往返时间的最小、最大 & 平均值

## 网络安全

## 网络实战
