面试前快速复习版。每节按“问题 → 标准回答 → 讲解 → 追问”展开。
1|问题:OSI 七层和 TCP/IP 四层怎么对应?
面试标准回答
OSI 从上到下是应用、表示、会话、传输、网络、数据链路和物理层。TCP/IP 把 OSI 上三层合为应用层,传输层和网络层分别对应,下面两层合为网络接口层。OSI 适合梳理职责,TCP/IP 更接近实际协议栈。
讲解
| OSI | 主要职责 | TCP/IP | 代表协议或数据 |
|---|---|---|---|
| 应用、表示、会话 | 应用服务、编码、会话 | 应用层 | HTTP、DNS |
| 传输 | 进程通信、可靠性 | 传输层 | TCP、UDP |
| 网络 | 寻址、跨网段路由 | 网际层 | IP |
| 数据链路、物理 | 本地链路交付、信号传输 | 网络接口层 | 以太网、Wi-Fi |
HTTP 消息 → TCP 段 → IP 包 → 以太网帧 → 比特流 加端口 加 IP 加 MAC发送端逐层加头,接收端逐层拆头。每层只解决一类问题:HTTP 表达业务,TCP 找进程并保证传输,IP 负责跨网络寻址,以太网把数据交给本地下一跳。
追问
- **四层和七层负载均衡?**四层主要看 IP、端口;七层还能看 HTTP 域名、路径和 Header。
- **交换机和路由器在哪层?**传统交换机工作在数据链路层,路由器工作在网络层。
2|问题:输入域名后,数据怎么找到目标主机?
面试标准回答
DNS 先把域名解析为 IP。主机再用目标 IP 和子网掩码判断是否同网段,并按最长前缀匹配查路由表。同网段时 ARP 查询目标 MAC;跨网段时查询网关 MAC,把 IP 包装进发往下一跳的帧,路由器再逐跳转发。
讲解
域名 ──DNS──> 目标 IP ↓ 查路由表 同网段 ──ARP 查目标 MAC──> 目标主机 跨网段 ──ARP 查网关 MAC──> 网关 ──逐跳路由──> 目标主机DNS 缓存未命中时,递归解析器通常依次询问根、顶级域和权威 DNS。转发过程中,链路层的源、目标 MAC 每一跳都会变化;端到端 IP 通常不变,但 TTL 会递减,经过 NAT 时 IP 和端口还可能被改写。
追问
- **为什么不查远端服务器的 MAC?**ARP 广播不跨路由器,只能找到本地链路上的下一跳。
- **多条路由都匹配怎么办?**选择前缀最长、范围最具体的一条。
3|问题:TCP 和 UDP 应该怎么选?
面试标准回答
文件、交易等不能缺字节的场景通常用 TCP,因为它提供有序、可靠的字节流;实时音视频更怕数据迟到,可以用 UDP,让应用决定哪些包要重传、哪些过期就丢。UDP 无连接、首部小,但不等于任何场景都更快。
讲解
| 维度 | TCP | UDP |
|---|---|---|
| 通信方式 | 有连接的字节流 | 无连接的数据报 |
| 消息边界 | 不保留 | 保留 |
| 可靠性 | 排序、确认、重传、去重 | 不保证送达和顺序 |
| 控制机制 | 流量控制、拥塞控制 | 由应用按需实现 |
| 首部 | 最小 20 字节 | 固定 8 字节 |
TCP 连接通常由源 IP、源端口、目标 IP、目标端口四元组标识。QUIC 虽然承载在 UDP 上,却自行实现了可靠传输和拥塞控制,所以“基于 UDP”和“不可靠”不能画等号。
追问
- **TCP 和 UDP 能用同一端口吗?**可以,内核会先按传输层协议分流。
- **服务端一个端口为何能接很多连接?**客户端 IP 或临时端口不同,连接四元组就不同。
4|问题:TCP 为什么要三次握手?
面试标准回答
三次握手用来可靠同步双方的初始序列号,并避免历史连接请求造成混淆。客户端先发 SYN 和序列号,服务端用 SYN+ACK 确认并给出自己的序列号,客户端最后回 ACK。两次握手少了对服务端序列号的确认,四次则可以把中间的 SYN 和 ACK 合并。
讲解
客户端 服务端CLOSED LISTEN │ SYN, seq=x ─────────────────────────> │ SYN-RECEIVED │ <────────── SYN+ACK, seq=y, ack=x+1 │ │ ACK, ack=y+1 ───────────────────────> │ESTABLISHED ESTABLISHED三次完成后,双方都确认了对方的初始序列号。报文丢失不会改流程:SYN 丢了由客户端重传,SYN+ACK 丢了由服务端重传,最后 ACK 丢了,服务端仍会重传 SYN+ACK。大量只发 SYN 的请求会占用半连接资源,可通过限速、清洗和 SYN cookies 缓解。
追问
- **第三次握手能带数据吗?**可以,此时客户端已确认服务端的序列号。
- **没调用
accept()能握手成功吗?**能,内核先完成握手,连接在 accept 队列等待应用取走。
5|问题:为什么通常是四次挥手?
面试标准回答
TCP 是全双工连接。收到 FIN 只表示对方不再发送,自己可能还有数据,因此两个方向要分别关闭,通常需要四个报文。主动关闭方进入 TIME_WAIT 等待 2MSL;CLOSE_WAIT 表示本地已收到 FIN,但应用还没有关闭套接字。
讲解
主动关闭方 被动关闭方FIN-WAIT-1 ── FIN ────────────────────> CLOSE-WAITFIN-WAIT-2 <─ ACK ───────────────────── <─ FIN ───────────────────── LAST-ACKTIME-WAIT ── ACK ─────────────────────> CLOSEDTIME_WAIT 能在最后 ACK 丢失时继续响应重传的 FIN,也给旧报文足够时间从网络中消失。CLOSE_WAIT 没有定时器替应用收尾,持续堆积通常说明代码漏了 close(),或关闭流程被阻塞。被动方没有剩余数据时,ACK 和 FIN 可以合并。
追问
- **TIME_WAIT 一定在客户端吗?**不一定,谁主动关闭,谁通常进入 TIME_WAIT。
- **CLOSE_WAIT 多怎么查?**定位进程和线程栈,检查异常分支、阻塞调用及连接是否及时关闭。
6|问题:TCP 如何保证可靠传输?
面试标准回答
TCP 用校验和发现损坏,用序列号排序去重,用累计 ACK 确认连续收到的位置,并通过超时或 3 个重复 ACK 触发重传。滑动窗口允许连续发送多段数据,SACK 还能告知已收到的字节区间,减少重复传输。
讲解
Seq=101 丢失Seq=201 ──> ACK=101 ①Seq=301 ──> ACK=101 ②Seq=401 ──> ACK=101 ③ ──> 快速重传 Seq=101
发送窗口:| 已确认 | 已发送未确认 | 可以发送 | 暂不可发送 |后续报文让接收方重复确认缺口,发送方收到 3 个重复 ACK 后不必等待超时。没有足够后续数据时,RTO 超时仍负责兜底,并会随连续超时退避。ACK 推进后,发送窗口才向右移动;SACK 只补充已收到的区间,不取代累计 ACK。
追问
- **一个 ACK 丢了就会重传吗?**不一定,后续更大的累计 ACK 可以一起确认前面的数据。
- **TCP 能保证业务数据不丢吗?**不能,进程崩溃、落库失败和业务确认要由应用处理。
7|问题:流量控制和拥塞控制有什么区别?
面试标准回答
流量控制保护接收端,由接收方用
rwnd通告剩余缓冲区;拥塞控制保护中间网络,由发送方根据网络反馈维护cwnd。实际可发送的在途数据受两者较小值限制。经典拥塞控制包括慢启动、拥塞避免、快速重传和快速恢复。
讲解
实际发送上限 = min(rwnd, cwnd)
接收端来不及处理 ──> rwnd 变小网络出现拥塞信号 ──> cwnd 变小接收方慢但网络空闲,应缩小 rwnd;接收方有空间但中间路由器丢包,应缩小 cwnd。经典慢启动阶段窗口按 RTT 快速增长,达到门限后转为较缓慢的拥塞避免。现代系统还可能采用 CUBIC、BBR,不能把所有实现都按 Reno 描述。
追问
- **接收窗口为零怎么办?**发送方暂停常规发送,并用窗口探测等待接收方恢复。
- **窗口越大越好吗?**不一定,还受内存和带宽时延积影响,过度排队会增加延迟。
8|问题:TCP 为什么会粘包,怎么拆包?
面试标准回答
TCP 是连续字节流,不保留应用消息边界。两次
send()可能被一次recv()读到,一次发送也可能分多次读取。应用协议必须自己定界,常见方案是固定长度、分隔符,或“长度字段 + 消息体”。
讲解
发送:[长度=5][hello][长度=3][bye]接收:[长度=5][he] [llo][长度=3][bye]解析:先读长度 → 累积足够字节 → 交付一条完整消息send() 只是把字节交给内核缓冲区,recv() 返回当时可读的部分,两者没有一一对应关系。所谓粘包是应用把读取次数误当成消息边界,不是 TCP 出错。UDP 保留数据报边界,但数据报过大仍可能触发 IP 分片。
追问
- **HTTP 如何定界?**HTTP/1.1 用 Content-Length、分块编码等规则;HTTP/2 和 HTTP/3 用带长度的帧。
- **读到半包怎么办?**先把数据留在缓冲区,等后续字节到齐再解析。