计算机网络面试题详解(19道核心高频题)
目录
1. TCP/IP 网络模型有几层?分别有什么用?
TCP/IP 模型采用 四层架构,与 OSI 七层模型对应关系如下:
| TCP/IP 层级 | OSI 对应层 | 核心功能 | 典型协议/设备 |
|---|---|---|---|
| 应用层 | 5-7层(会话、表示、应用) | 为应用程序提供网络服务接口 | HTTP、FTP、SMTP、DNS |
| 传输层 | 第4层(传输层) | 端到端通信、可靠性保障 | TCP、UDP |
| 网络层 | 第3层(网络层) | 寻址、路由选择、分组转发 | IP、ICMP、ARP、路由器 |
| 网络接口层 | 1-2层(物理、数据链路) | 物理传输、帧封装、MAC寻址 | 以太网、WiFi、网卡、交换机 |
关键理解:
-
应用层:直接为用户程序服务(浏览器、邮件客户端)
-
传输层:负责进程到进程的通信(通过端口号区分)
-
网络层:负责主机到主机的通信(通过 IP 地址路由)
-
网络接口层:负责节点到节点的物理信号传输
2. 介绍一下 HTTP 协议吧
HTTP(HyperText Transfer Protocol) 是应用层协议,用于客户端(浏览器)与服务器之间的超文本传输。
核心特性
| 特性 | 说明 |
|---|---|
| 基于请求-响应模型 | 客户端主动发起请求,服务器被动响应 |
| 无状态(Stateless) | 每次请求独立,服务器不保存客户端上下文(需 Cookie/Session 解决) |
| 无连接 | HTTP/1.0 默认短连接;HTTP/1.1 起支持持久连接(Keep-Alive) |
| 灵活可扩展 | 通过 Header 携带元数据,支持任意类型数据传输 |
| 明文传输 | HTTP 本身不加密,易被窃听(HTTPS 解决) |
报文结构
请求报文: 请求行(方法 + URL + 版本)→ GET /index.html HTTP/1.1 请求头(Key: Value) → Host: www.example.com 空行 请求体(POST 数据等) → username=admin 响应报文: 状态行(版本 + 状态码 + 原因)→ HTTP/1.1 200 OK 响应头 → Content-Type: text/html 空行 响应体(HTML/JSON 等) → <html>...</html>
3. GET 和 POST 有什么区别?
| 对比维度 | GET | POST |
|---|---|---|
| 语义 | 获取资源(Read) | 提交数据(Create/Update) |
| 参数位置 | URL 查询字符串(?key=value) | 请求体(Body)中 |
| 数据大小 | 受 URL 长度限制(通常 2KB-8KB) | 理论上无限制(受服务器配置约束) |
| 安全性 | 参数暴露在 URL,不安全(不适合传密码) | 参数在 Body 中,相对安全(但仍需 HTTPS 防窃听) |
| 幂等性 | 幂等(多次请求结果相同,无副作用) | 非幂等(多次提交可能创建多条记录) |
| 缓存 | 可被浏览器缓存 | 默认不被缓存 |
| 书签/历史 | 参数保留在 URL,可收藏 | 不会保留在 URL 中 |
| 编码类型 | application/x-www-form-urlencoded | 支持多种(multipart/form-data 用于文件上传) |
本质区别:GET 是幂等的读取操作,POST 是非幂等的写入操作。这是 RESTful 设计的核心原则,而非单纯的技术差异。
4. PING 的作用?
PING(Packet Internet Groper) 是基于 ICMP 协议 的网络诊断工具。
主要作用
-
测试网络连通性:验证本地主机与目标主机之间 IP 层是否可达
-
测量网络延迟:通过往返时间(RTT)评估网络质量
-
检测丢包率:统计丢包情况判断网络稳定性
-
解析域名:自动将域名解析为 IP 地址(DNS 验证)
工作原理
本地主机 → 发送 ICMP Echo Request 数据包 → 目标主机 本地主机 ← 接收 ICMP Echo Reply 数据包 ← 目标主机
关键指标解读
| 指标 | 含义 | 正常范围 |
|---|---|---|
| TTL(Time To Live) | 数据包存活跳数(经过的路由器数量) | 通常 64/128/255 |
| time | 往返延迟时间 | < 100ms 优秀,< 300ms 可接受 |
| 丢包率 | 未收到响应的比例 | 0% 为理想状态 |
常用命令:
ping www.baidu.com # 基础测试 ping -c 4 -i 0.5 8.8.8.8 # 发送4次,间隔0.5秒 ping -t 192.168.1.1 # Windows 持续 ping(直到 Ctrl+C)
5. 常见的 HTTP 状态码有哪些
2xx 成功状态码
| 状态码 | 含义 | 场景 |
|---|---|---|
| 200 OK | 请求成功 | 标准成功响应 |
| 201 Created | 已创建 | POST 请求创建资源成功 |
| 204 No Content | 无内容 | 删除成功或无需返回体 |
3xx 重定向状态码
| 状态码 | 含义 | 场景 |
|---|---|---|
| 301 Moved Permanently | 永久重定向 | 域名更换、HTTP 转 HTTPS |
| 302 Found | 临时重定向 | 未登录跳转登录页(可能改变请求方法) |
| 304 Not Modified | 未修改 | 协商缓存命中,直接使用本地缓存 |
4xx 客户端错误状态码
| 状态码 | 含义 | 场景 |
|---|---|---|
| 400 Bad Request | 请求语法错误 | 参数格式错误、JSON 解析失败 |
| 401 Unauthorized | 未认证 | 缺少 Token、未登录 |
| 403 Forbidden | 禁止访问 | 无权限访问该资源 |
| 404 Not Found | 资源不存在 | URL 错误、资源已删除 |
| 405 Method Not Allowed | 方法不允许 | 如用 GET 访问只支持 POST 的接口 |
| 429 Too Many Requests | 请求过多 | 触发限流策略 |
5xx 服务器错误状态码
| 状态码 | 含义 | 场景 |
|---|---|---|
| 500 Internal Server Error | 服务器内部错误 | 代码异常、未捕获错误 |
| 502 Bad Gateway | 网关错误 | Nginx 无法连接到后端服务 |
| 503 Service Unavailable | 服务不可用 | 服务器过载、维护中 |
| 504 Gateway Timeout | 网关超时 | 后端处理超时(如超过 30s) |
6. HTTP1.1 和 HTTP1.0 的区别有哪些?
| 特性 | HTTP/1.0 | HTTP/1.1 |
|---|---|---|
| 连接机制 | 短连接(每次请求新建 TCP 连接) | 持久连接(Keep-Alive,复用 TCP) |
| 管道化(Pipelining) | 不支持 | 支持(客户端可连续发多个请求,但存在队头阻塞) |
| Host 头 | 非必需 | 强制要求(支持虚拟主机,同一 IP 多域名) |
| 缓存机制 | 简单(Expires、Last-Modified) | 增强(Cache-Control、ETag、协商缓存) |
| 断点续传 | 不支持 | 支持(Range 头,分片下载/多线程下载) |
| 错误码 | 较少 | 新增 410、409 等更细粒度状态码 |
| 请求方法 | GET、POST、HEAD | 新增 PUT、DELETE、OPTIONS、TRACE、CONNECT |
核心改进:HTTP/1.1 通过持久连接大幅减少 TCP 三次握手开销,但队头阻塞(Head-of-Line Blocking)问题仍未解决。
7. HTTPS 和 HTTP 的区别是什么?
| 对比项 | HTTP | HTTPS |
|---|---|---|
| 安全性 | 明文传输,易被窃听、篡改、冒充 | 加密传输,防窃听、防篡改、身份认证 |
| 默认端口 | 80 | 443 |
| 协议层 | 应用层直接到 TCP | 应用层 → SSL/TLS → TCP |
| 证书 | 不需要 | 需要 CA 数字证书 |
| 性能 | 较快(无加密开销) | 略慢(握手阶段增加 RTT,加密有计算开销) |
| SEO | 无优势 | 搜索引擎优先收录 |
HTTPS 加密流程(TLS 握手)
1. 客户端 → 支持的加密套件列表 + 随机数(Client Hello) 2. 服务端 → 选定加密套件 + 证书 + 随机数(Server Hello) 3. 客户端 → 验证证书 → 生成预主密钥 → 用公钥加密发送 4. 服务端 → 用私钥解密获取预主密钥 5. 双方 → 通过随机数+预主密钥生成会话密钥(对称加密) 6. 后续通信 → 使用会话密钥对称加密传输
关键点:TLS 握手使用非对称加密交换密钥,后续通信使用对称加密提高效率。
8. HTTP2 和 HTTP1.1 的区别是什么?
| 特性 | HTTP/1.1 | HTTP/2 |
|---|---|---|
| 传输格式 | 纯文本(可读但冗长) | 二进制分帧(高效、易解析) |
| 多路复用 | 单连接单请求(队头阻塞) | 单连接多请求并行(Stream 流) |
| 头部压缩 | 无压缩(Cookie 等重复传输) | HPACK 算法压缩头部 |
| 服务器推送 | 客户端主动请求 | Server Push(服务端主动推送资源) |
| 优先级 | 无 | 可设置请求优先级 |
| 队头阻塞 | 应用层阻塞(浏览器限制并发数) | 解决应用层队头阻塞(但 TCP 层仍存在) |
核心机制图解
HTTP/1.1: HTTP/2: 请求1 → 等待响应 → 请求2 流1: 请求A ──┐ ↑ 阻塞 → 流2: 请求B ──┼→ 单连接多路复用 请求2 必须等请求1完成 流3: 请求C ──┘
注意:HTTP/2 虽然解决了应用层队头阻塞,但底层仍依赖 TCP,TCP 层队头阻塞(丢包导致后续数据等待)在 HTTP/3 才彻底解决。
9. HTTP3 和 HTTP2 的区别是什么?
| 特性 | HTTP/2 | HTTP/3 |
|---|---|---|
| 传输层协议 | TCP + TLS | QUIC(基于 UDP) |
| 连接建立 | TCP 三次握手 + TLS 握手(2-3 RTT) | 0-RTT 或 1-RTT(快速握手) |
| 队头阻塞 | TCP 层仍存在(丢包阻塞所有流) | 彻底解决(基于 UDP 的独立流) |
| 连接迁移 | 不支持(IP 变化需重连) | 支持(连接 ID 标识,WiFi/4G 切换无感知) |
| 安全性 | TLS 可选版本 | 强制 TLS 1.3 |
| 拥塞控制 | 内核 TCP 实现 | 用户空间实现,可快速迭代 |
QUIC 协议优势
传统 TCP+TLS: QUIC over UDP: TCP 握手(1 RTT) QUIC 握手(1 RTT,内含加密) TLS 握手(1-2 RTT) 0-RTT 恢复(之前连接过) 总计: 2-3 RTT 总计: 0-1 RTT
适用场景:移动网络(频繁切换网络)、弱网环境、实时性要求高的应用(直播、游戏)。
10. TCP 建立连接的过程是怎样的?
三次握手(Three-way Handshake):
客户端 服务端 | SYN=1, seq=x | | ─────────────────────>| | (请求建立连接,初始序列号x)| | | | SYN=1, ACK=1, seq=y, | | ack=x+1 | |<────────────────────── | | (同意建立,初始序列号y,期待x+1)| | | | ACK=1, seq=x+1, | | ack=y+1 | | ─────────────────────>| | (确认收到,期待y+1) | | | 连接建立,开始数据传输
关键字段说明
| 字段 | 作用 |
|---|---|
| SYN | 同步序列号,用于发起连接 |
| ACK | 确认应答,ack = 对方 seq + 1 |
| seq | 本方发送数据的起始序列号(随机生成防攻击) |
| ack | 期待对方下一次发送的序列号 |
11. 为什么是三次握手?
核心目的:确保双方的发送和接收能力都正常,并同步初始序列号。
两次握手不行吗?
假设只有两次握手:
客户端发送 SYN,服务端回复 SYN+ACK 后认为连接建立。 但如果 SYN 在网络中延迟,客户端重发 SYN,服务端会建立两个连接! 或者服务端回复的 SYN+ACK 丢失,客户端不知道服务端是否收到。
三次握手的必要性证明
| 握手次数 | 验证能力 | 问题 |
|---|---|---|
| 1 次 | 仅客户端知道能发 | 服务端无法确认客户端是否收到 |
| 2 次 | 客户端知道能收发,服务端知道能收 | 服务端不知道客户端是否能收(自己的 SYN 对方是否收到?) |
| 3 次 | 双方都知道能收发 | ✅ 完整验证 |
通俗理解:
-
第一次:客户端说"我能发,你在吗?"(服务端知道客户端能发)
-
第二次:服务端说"我在,我能发,你能收吗?"(客户端知道服务端能收发)
-
第三次:客户端说"我能收,开始吧!"(服务端知道客户端能收)
历史原因:三次握手也防止了已失效的连接请求报文突然到达服务端造成错误(如延迟的 SYN 导致脏连接)。
12. TCP 断开连接的过程是怎样的?
四次挥手(Four-way Handshake):
客户端 服务端 | FIN=1, seq=u | | ─────────────────────>| | (数据发完了,请求关闭) | | | | ACK=1, seq=v, | | ack=u+1 | |<────────────────────── | | (知道你要关了,但我还有数据)| | | | [服务端继续发数据] | | | | FIN=1, ACK=1, | | seq=w, ack=u+1 | |<────────────────────── | | (我也发完了,可以关了) | | | | ACK=1, seq=u+1, | | ack=w+1 | | ─────────────────────>| | (确认关闭) | | | 等待 2MSL 后彻底关闭 立即关闭
为什么有 TIME_WAIT 状态?
客户端最后发送 ACK 后进入 TIME_WAIT(2MSL),确保:
-
最后一个 ACK 能被服务端收到(如果丢失,服务端会重发 FIN)
-
让旧连接的报文在网络中消失,避免影响新连接
13. 第四次挥手为什么要等待 2MSL(60s)
MSL(Maximum Segment Lifetime):报文最大生存时间,RFC 793 建议 2 分钟,Linux 通常设为 30 秒,故 2MSL = 60 秒。
两个核心原因
| 原因 | 说明 |
|---|---|
| 可靠终止连接 | 确保最后一个 ACK 丢失后,能收到服务端重传的 FIN 并重新确认 |
| 防止旧报文干扰 | 让本次连接的所有报文从网络中消失,避免下一个新连接收到旧数据 |
场景演示
场景:最后一个 ACK 丢失 1. 客户端发送 ACK 后进入 TIME_WAIT 2. 服务端未收到 ACK,超时后重发 FIN 3. 客户端在 2MSL 内收到 FIN,重发 ACK,服务端正常关闭 4. 如果客户端立即关闭(不等待),服务端永远收不到确认,保持半关闭状态
不等待的风险:
-
立即重用端口建立新连接,可能收到旧连接的迟到的 FIN/RST,导致数据混乱
-
服务端长时间处于 LAST_ACK 状态,资源无法释放
14. 为什么是四次挥手?
根本原因:TCP 连接是全双工的,双方需要独立关闭自己的发送通道。
为什么不能三次?
合并第二次和第三次?即服务端收到 FIN 后立即回复 FIN+ACK? 不行!因为服务端可能还有数据要发。
| 阶段 | 说明 |
|---|---|
| 第一次 | 客户端 → 服务端:我发完了(FIN) |
| 第二次 | 服务端 → 客户端:知道了(ACK),但我可能还有数据要发 |
| 第三次 | 服务端 → 客户端:我也发完了(FIN) |
| 第四次 | 客户端 → 服务端:知道了(ACK) |
对比三次握手:握手时 SYN 和 ACK 可以合并(因为连接建立前无数据),但挥手时中间可能有数据传输,必须分开确认。
15. TCP 滑动窗口是什么?
滑动窗口(Sliding Window) 是 TCP 流量控制的核心机制,用于动态调整发送方的数据发送速率。
窗口类型
| 窗口 | 作用 | 控制方 |
|---|---|---|
| 发送窗口 | 限制发送方未确认的数据量 | 接收方通告的窗口大小 |
| 接收窗口 | 限制接收方缓冲区剩余空间 | 接收方根据处理能力调整 |
工作原理
发送方窗口(假设大小为 4): 已发送已确认 | 已发送未确认 | 可发送未发送 | 不可发送 [1,2] | [3,4,5,6] | [7,8] | [9...] ↑ 滑动窗口在此移动 当收到 ACK=3(确认3之前都收到): [1,2,3] | [4,5,6,7] | [8,9] | [10...] 窗口向右滑动
窗口缩放
TCP 头部窗口字段只有 16 位(最大 64KB),现代高速网络不够用。TCP 选项中的窗口缩放因子(Window Scale)可将窗口扩大 2^14 倍,支持 GB 级窗口。
16. 发送方一直发送数据,但是接收方处理不过来怎么办?(流量控制)
解决方案:TCP 流量控制(Flow Control)
机制详解
-
接收窗口通告(Window Advertisement)
-
接收方在 ACK 报文中携带
rwnd(接收窗口剩余大小) -
发送方根据
rwnd调整发送量,确保已发送未确认 ≤ rwnd
-
-
零窗口探测
-
当
rwnd=0时,发送方停止发送 -
启动持续定时器,定期发送窗口探测报文(1 字节数据)
-
接收方回复当前窗口大小,打破死锁
-
流量控制 vs 拥塞控制
| 维度 | 流量控制(Flow Control) | 拥塞控制(Congestion Control) |
|---|---|---|
| 目的 | 防止接收方被压垮 | 防止网络被压垮 |
| 控制对象 | 端到端的发送速率 | 全局网络负载 |
| 反馈来源 | 接收方 ACK 中的窗口字段 | 丢包、延迟等网络状态 |
| 算法 | 滑动窗口 | 慢启动、拥塞避免、快重传 |
17. TCP 半连接队列和全连接队列是什么?
发生在服务端收到客户端 SYN 请求后的连接建立阶段:
客户端 SYN ──→ 服务端 ↓ [半连接队列 / SYN Queue] 存放 SYN_RCVD 状态的连接 (收到 SYN,未收到 ACK) ↓ 收到客户端 ACK 后 ↓ [全连接队列 / Accept Queue] 存放 ESTABLISHED 状态的连接 等待应用层 accept() ↓ 应用 accept() 取走连接
队列溢出攻击
| 攻击类型 | 原理 | 防御 |
|---|---|---|
| SYN Flood | 伪造大量 SYN 占满半连接队列,使正常请求无法进入 | SYN Cookies(不分配资源,用加密验证) |
| 全连接队列满 | 应用处理慢,队列满后新连接被丢弃 | 调大 backlog,优化应用性能 |
Linux 参数调优
# 半连接队列长度(受 net.ipv4.tcp_max_syn_backlog 和 listen() 的 backlog 共同影响) net.ipv4.tcp_max_syn_backlog = 65536 # 开启 SYN Cookies net.ipv4.tcp_syncookies = 1 # 全连接队列长度(应用 listen() 的 backlog) # 查看当前队列状态:ss -lnt
18. 粘包/拆包是怎么发生的?怎么解决这个问题?
粘包(Packet Sticking):接收方一次读到多个发送方的数据包 拆包(Packet Splitting):接收方一次只读到发送方数据包的一部分
根本原因
TCP 是字节流协议,无消息边界概念。发送方 send() 次数与接收方 recv() 次数无对应关系,数据在传输层被合并或拆分。
发送方:send("Hello") + send("World")
传输层可能合并为 "HelloWorld" → 接收方一次 recv 读到(粘包)
发送方:send("HelloWorld") 较大
传输层拆分为两个包 → 接收方两次 recv 读到 "Hell" 和 "oWorld"(拆包)
解决方案
| 方案 | 原理 | 实现 |
|---|---|---|
| 固定长度 | 每个消息固定 N 字节,不足补空 | 简单但浪费带宽 |
| 分隔符 | 消息间用特殊字符分隔(如 \n) | 需转义分隔符本身 |
| 长度前缀 | 消息头 4 字节表示消息体长度 | 最常用,高效灵活 |
| 特殊协议 | 如 HTTP 的 Content-Length、Chunked | 应用层协议内置 |
长度前缀方案示例
消息格式:[4字节长度][N字节内容] 发送 "Hello":0x00 0x00 0x00 0x05 "Hello" 接收方:先读 4 字节得长度 5,再读 5 字节得内容
19. 浏览器地址栏输入网站按回车后发生了什么?
完整流程全景图
1. URL 解析 └─ 协议、域名、路径、参数提取 2. DNS 解析(域名 → IP) └─ 浏览器缓存 → OS 缓存 → hosts → 本地 DNS → 递归查询 → 根/顶级/权威 DNS 3. 建立 TCP 连接 └─ 三次握手(HTTP/1.1)或 QUIC 握手(HTTP/3) 4. TLS 握手(HTTPS) └─ 交换密钥,建立加密通道 5. 发送 HTTP 请求 └─ 构建请求行、Header、Cookie 等 6. 服务器处理 └─ 反向代理 → Web 服务器 → 应用服务器 → 数据库/缓存查询 7. 返回 HTTP 响应 └─ 状态码、响应头、HTML 主体 8. 浏览器渲染 └─ 解析 HTML → 构建 DOM → CSS 计算 → 布局 → 绘制 → 合成 9. 加载资源 └─ 解析 HTML 中的 JS/CSS/图片,重复 3-8 步骤(HTTP/2 多路复用优化) 10. 执行 JavaScript └─ 可能修改 DOM,触发重排重绘
关键优化点
| 阶段 | 优化手段 |
|---|---|
| DNS | DNS 预解析 <link rel="dns-prefetch">、HTTPDNS |
| TCP/TLS | 连接复用(Keep-Alive)、TLS 1.3(1-RTT)、QUIC(0-RTT) |
| 传输 | HTTP/2 多路复用、资源压缩(Gzip/Brotli)、CDN 边缘缓存 |
| 渲染 | 关键渲染路径优化、懒加载、预加载 <link rel="preload"> |
总结
题覆盖了网络面试的核心知识体系:
-
基础架构:TCP/IP 四层模型
-
应用协议:HTTP 演进(0.9 → 1.0 → 1.1 → 2 → 3)、HTTPS 安全机制
-
传输层:TCP 三次握手/四次挥手、滑动窗口、流量控制、拥塞控制
-
工程实践:粘包拆包处理、队列优化、浏览器渲染全流程
面试建议:不仅要记住答案,更要理解设计背后的权衡(如为什么 TCP 可靠但慢,UDP 快但不可靠),并能结合实际场景(如直播选 UDP、文件传输选 TCP)进行分析。
如果这篇文章对你有帮助,欢迎点赞收藏!有任何问题可以在评论区留言讨论。
8610

被折叠的 条评论
为什么被折叠?



