计算机网络 TCP篇常见面试题总结

目录

[TCP 的三次握手与四次挥手详解](#TCP 的三次握手与四次挥手详解)

[1. 三次握手(Three-Way Handshake)](#1. 三次握手(Three-Way Handshake))

[2. 四次挥手(Four-Way Handshake)](#2. 四次挥手(Four-Way Handshake))

[TCP 为什么可靠?](#TCP 为什么可靠?)

[1. 序列号与确认应答(ACK)](#1. 序列号与确认应答(ACK))

[2. 超时重传(Retransmission)](#2. 超时重传(Retransmission))

[3. 滑动窗口(Sliding Window)](#3. 滑动窗口(Sliding Window))

[4. 拥塞控制(Congestion Control)](#4. 拥塞控制(Congestion Control))

[5. 校验和(Checksum)](#5. 校验和(Checksum))

[6. 面向连接](#6. 面向连接)

总结对比

TCP滑动窗口

三次握手期间的窗口协商

数据传输阶段的窗口动态调整

关键细节补充

[1. 窗口大小与拥塞控制的关系](#1. 窗口大小与拥塞控制的关系)

[2. 糊涂窗口综合征(SWS)](#2. 糊涂窗口综合征(SWS))

[3. 窗口探测(Window Probe)](#3. 窗口探测(Window Probe))

TCP和UDP有什么区别

核心设计目标

协议格式对比

TCP报文结构

UDP报文结构

典型应用场景

可靠性机制对比

总结选择策略

TCP的粘包和拆包

基本概念

成因分析

如何解决粘包和拆包


TCP 的三次握手与四次挥手详解

1. 三次握手(Three-Way Handshake)

TCP 建立连接时通过三次握手同步初始序列号(ISN)并协商窗口大小,确保双方具备发送和接收能力。流程如下:

  • 客户端 → 服务器(SYN 包)

    • 客户端发送 SYN 包,携带初始序列号(ISN<sub>c</sub>)和窗口大小,请求建立连接。
    • 标志位:SYN=1ACK=0
  • 服务器 → 客户端(SYN+ACK 包)

    • 服务器收到 SYN 后,分配资源并发送 SYN+ACK 包:
      • 确认号(ACK)= ISN<sub>c</sub>+1(表示已收到客户端 SYN)。
      • 自身初始序列号(ISN<sub>s</sub>)和窗口大小。
    • 标志位:SYN=1ACK=1
  • 客户端 → 服务器(ACK 包)

    • 客户端收到 SYN+ACK 后,发送 ACK 包:
      • 确认号(ACK)= ISN<sub>s</sub>+1(表示已收到服务器 SYN)。
    • 此时双方进入ESTABLISHED状态,开始传输数据。

关键作用

  • 防止过时的连接请求(如网络延迟导致的重复 SYN)干扰新连接。
  • 同步双方初始序列号,为可靠传输奠定基础。
2. 四次挥手(Four-Way Handshake)

TCP 关闭连接时通过四次挥手确保数据完全传输完毕。流程如下:

  • 主动关闭方 → 被动关闭方(FIN 包)

    • 主动方(如客户端)发送 FIN 包,表示 "我已无数据要发送",但仍可接收数据。
    • 标志位:FIN=1ACK=1
  • 被动关闭方 → 主动关闭方(ACK 包)

    • 被动方(如服务器)确认 FIN,发送 ACK 包:
      • 确认号(ACK)= 收到的 FIN 序列号 + 1。
    • 此时主动方进入FIN_WAIT_2 状态,被动方进入CLOSE_WAIT状态。
  • 被动关闭方 → 主动关闭方(FIN 包)

    • 被动方数据发送完毕后,发送 FIN 包,表示 "我也无数据要发送"。
    • 标志位:FIN=1ACK=1
  • 主动关闭方 → 被动关闭方(ACK 包)

    • 主动方确认 FIN,发送 ACK 包:
      • 确认号(ACK)= 收到的 FIN 序列号 + 1。
    • 主动方进入TIME_WAIT状态(持续 2MSL,防止 ACK 丢失导致被动方重发 FIN),最终双方关闭连接(确保至少留有一次ACK丢失的容错)。

关键作用

  • 确保双方数据均已完全发送和接收。
  • 优雅释放网络资源,避免端口占用。

TCP 为什么可靠?

TCP 通过以下机制实现可靠传输:

1. 序列号与确认应答(ACK)
  • 序列号(Sequence Number)
    每个 TCP 段携带数据的首字节序列号,接收方通过序列号按序重组数据。
  • 确认应答(ACK)
    接收方返回的 ACK 号表示 "期望接收的下一个字节序列号",确保数据不丢失。
    例如:若发送方发送序列号 100-200 的数据包,接收方返回 ACK=201,表示已收到 100-200 并期待 201。
2. 超时重传(Retransmission)
  • 发送方为每个数据包设置定时器,若超时未收到 ACK,则重发该数据包。
  • 快速重传:若接收方连续收到 3 个相同 ACK(如 ACK=201),表明中间段(如 201-300)丢失,发送方立即重传,无需等待超时。
3. 滑动窗口(Sliding Window)
  • 动态调整发送窗口和接收窗口大小,实现流量控制:
    • 发送窗口 = min (接收方通告窗口,拥塞窗口)。
    • 接收方通过 ACK 中的窗口字段告知发送方自身缓冲区剩余空间,防止过载。
4. 拥塞控制(Congestion Control)
  • 防止网络过载,通过调整拥塞窗口(cwnd)实现:
    • 慢启动:初始 cwnd=1MSS,每收到一个 ACK 则 cwnd+1,指数增长至阈值(ssthresh)。
    • 拥塞避免:超过阈值后,每轮 RTT 仅 cwnd+1,线性增长。
    • 拥塞发生时:将 ssthresh 降至当前 cwnd 的一半,cwnd 重置为 1MSS,重新进入慢启动。
5. 校验和(Checksum)
  • 每个 TCP 段包含校验和字段,接收方通过校验和验证数据完整性,若错误则丢弃并等待重传。
6. 面向连接
  • 通过三次握手建立连接,四次挥手关闭连接,确保双方状态同步,避免数据丢失。
总结对比
特性 三次握手 四次挥手 TCP 可靠性机制
目的 建立连接,同步 ISN 和窗口大小 关闭连接,确保数据完全传输 保证数据准确、有序、无丢失
核心动作 SYN → SYN+ACK → ACK FIN → ACK → FIN → ACK 序列号、ACK、重传、窗口、校验和
状态转换 CLOSED → SYN_SENT → ESTABLISHED ESTABLISHED → FIN_WAIT_1 → ... → CLOSED 持续维护发送 / 接收状态
可靠性保障 防止过时连接干扰 确保资源优雅释放 端到端的数据传输质量保证

TCP滑动窗口

TCP 滑动窗口的初始值是在三次握手过程中协商确定的,之后在数据传输阶段会根据网络状况和接收方缓冲区状态动态调整。具体机制如下:

三次握手期间的窗口协商

初始窗口大小的交换

  • 客户端 → 服务器(SYN 包)
    客户端在 SYN 包中通过Window Size字段(16 位)告知服务器自己初始接收窗口的大小 (单位:字节)。例如,若客户端发送Window = 65535,表示客户端初始能接收 65535 字节的数据。
  • 服务器 → 客户端(SYN+ACK 包)
    服务器在响应的 SYN+ACK 包中,同样通过Window Size字段告知客户端自己的初始接收窗口大小。
  • 窗口扩大因子(Window Scaling)
    若双方支持Window Scaling选项(通过 TCP 选项协商),实际窗口大小 = 窗口字段值 × 2^ 缩放因子(例如,缩放因子为 2,则窗口大小 = 65535×4=262140 字节)。
数据传输阶段的窗口动态调整

窗口滑动机制

  • 发送方窗口
    发送方维护两个指针:SND.UNA(已发送但未确认的最早字节)和SND.NXT(下一个要发送的字节),窗口大小 = 接收方通告的窗口值(通过 ACK 包携带)。
  • 接收方窗口
    接收方通过 ACK 包中的Window字段告知发送方自己当前的可用缓冲区大小。例如:
    • 若接收方处理数据缓慢,缓冲区接近满,则发送Window = 0,触发发送方的窗口探测机制
    • 若接收方处理完一批数据,缓冲区空闲,则增大窗口值(如Window = 131072)。
关键细节补充
1. 窗口大小与拥塞控制的关系
  • 实际发送窗口 = min (接收方通告窗口,拥塞窗口)
    接收方窗口由接收方缓冲区决定,拥塞窗口由发送方根据网络拥塞情况动态调整(如慢启动、拥塞避免算法)。
2. 糊涂窗口综合征(SWS)
  • 接收方优化
    若接收方缓冲区仅释放少量空间(如 512 字节),可能暂不发送窗口更新,而是等待缓冲区释放更多空间(如≥MSS)后再通知发送方。
  • 发送方优化
    若发送方有少量数据(如 100 字节)要发送,可能等待积累到 MSS(如 1460 字节)后再发送,避免产生小数据包。
3. 窗口探测(Window Probe)
  • 当接收方窗口为 0 时,发送方会定期发送窗口探测包(仅含 1 字节数据),迫使接收方返回最新窗口大小,防止连接饿死。

TCP和UDP有什么区别

核心设计目标
TCP UDP
面向连接:通过三次握手建立连接,四次挥手关闭连接,确保通信双方状态同步。 无连接:无需建立连接,直接发送数据,资源开销小。
可靠传输:确保数据准确、有序到达,通过序列号、ACK、重传等机制实现。 不可靠传输:不保证数据到达顺序或完整性,可能丢包、乱序。
流量控制:通过滑动窗口动态调整发送速率,避免接收方过载。 无流量控制:发送方按固定速率发送,接收方可能因来不及处理而丢包。
拥塞控制:根据网络拥塞状态调整发送窗口,避免网络崩溃。 无拥塞控制:可能导致网络拥塞(如 UDP 洪水攻击)。
协议格式对比
字段 TCP 头部(20 字节基础) UDP 头部(8 字节)
源端口 16 位 16 位
目的端口 16 位 16 位
序列号 32 位(用于有序重组数据)
确认号 32 位(用于 ACK 应答)
窗口大小 16 位(用于流量控制)
校验和 16 位(强制) 16 位(可选,IPv4 中可忽略)
标志位 SYN、ACK、FIN、RST、PSH、URG 等
TCP报文结构
UDP报文结构
指标 TCP UDP
传输效率 低(头部开销大,需维护连接状态) 高(头部仅 8 字节,无连接开销)
实时性 低(重传、排序等引入延迟) 高(无重传,延迟小)
吞吐量 稳定(拥塞控制避免网络崩溃) 不稳定(可能因网络拥塞丢包)
资源占用 高(需维护连接状态表) 低(无连接状态)
典型应用场景
场景 TCP 适用 UDP 适用
Web 浏览(HTTP) ✅ 需可靠传输,避免页面错乱 ❌ 不可靠传输可能导致页面缺失
文件传输(FTP) ✅ 确保文件完整无误 ❌ 丢包会导致文件损坏
电子邮件(SMTP) ✅ 邮件内容必须完整送达 ❌ 不可靠传输会导致邮件丢失
实时音视频 ❌ 重传会加剧延迟,影响体验 ✅ 容忍少量丢包,优先保证实时性
DNS 查询 ❌ 单次查询延迟高(需握手) ✅ 快速响应,少量丢包可重试
游戏联机 ❌ 角色位置同步需低延迟 ✅ 允许少量预测误差,优先流畅性
可靠性机制对比
机制 TCP UDP
连接管理 三次握手建立连接,四次挥手关闭 无连接过程
序列号与 ACK 强制使用,确保数据有序性
超时重传 支持(快速重传 + 超时重传) 无(需应用层自行实现)
滑动窗口 支持流量控制和拥塞控制
错误校验 强制校验和,保证数据完整性 可选校验和(IPv4 中常忽略)
总结选择策略
  • 选 TCP:当可靠性比性能更重要时(如文件传输、网页浏览)。
  • 选 UDP:当实时性比可靠性更重要时(如视频会议、游戏),或应用层自行实现可靠性机制(如 QUIC 协议)。

TCP的粘包和拆包

基本概念

TCP 是面向字节流的协议,其传输的数据无边界 。发送方连续发送的多个数据包(如多次send()),在接收方可能呈现为:

  • 粘包:多个数据包被 "粘" 在一起,接收方一次读取到多个完整或不完整的包。
  • 拆包:一个数据包被 "拆分" 成多次接收,接收方需多次读取才能获取完整包。

示例场景

发送方依次发送两个数据包:[数据包1][数据包2],接收方可能收到:

  • 粘包[数据包1+数据包2](一次读取两个包)。
  • 拆包[数据包1的前半部分][数据包1的后半部分+数据包2](两次读取才完整)。
成因分析

TCP 粘包 / 拆包由以下因素共同导致:

  • TCP 的 Nagle 算法

    • 为减少网络中小数据包的数量,Nagle 算法会将短时间内的小数据包合并发送。
    • 例如:发送方先后调用send("HELLO")send("WORLD"),可能被合并为"HELLOWORLD"发送。
  • TCP 滑动窗口与拥塞控制

    • 发送窗口大小动态调整,若窗口较小,一个完整包可能被拆分为多次发送。
    • 例如:窗口大小为 1000 字节,而数据包大小为 1500 字节,则会被拆分为两个片段。
  • 接收缓冲区管理

    • 接收方缓冲区已满时,未完全接收的包会暂存,导致后续数据包与残留数据 "粘" 在一起。
  • 网络延迟与 MTU 限制

    • 网络层最大传输单元(MTU,通常为 1500 字节)会限制 TCP 数据包的大小,超过 MTU 的包会被 IP 层分片。
如何解决粘包和拆包
  • 粘包:这个思路其实很清晰,就是把它拆开呗,具体就是看怎么拆了,比如我们可以固定长度,我们规定每个包都是10个字节,那么就10个字节切一刀,这样拆开解析就ok了。
  • 半包:半包其实就是信息还不完整,我们需要等接收到全部的信息之后再作处理,当我们识别这是一个不完整的包时候,我们先hold住,不作处理,等待

数据完整再处理。这里关键点在于,我们如何才能知道此时完整了?上面说的固定长度其实也是一点,当然还有更多更好的解决方案,我们接着往下看。

实际常见解决粘包与半包问题有三个方案:

  • 固定长度:
  1. 每个数据包的总长度固定,不足部分填充特定字符(如\0)。
  2. 接收方按固定长度读取数据,确保每次读取对应一个完整包。
优点 缺点
实现简单 浪费带宽(需填充)
无需维护缓冲区 不适合变长数据
解析速度快 需预估最大长度
  • 分隔符
  1. 使用特殊字符(如\r\n\0)标记数据包的结束。
  2. 接收方需维护缓冲区,累积数据直到找到分隔符。
优点 缺点
灵活支持变长数据 需维护缓冲区
适合文本协议(如 HTTP) 分隔符可能出现在数据中
实现较简单 性能略低于固定长度
  • 固定长度字段+内容
  1. 在数据包头部添加固定长度的字段(如 4 字节整数),指示包的总长度。
  2. 接收方先读取长度字段,再按长度读取完整数据。
优点 缺点
高效处理任意长度数据 实现复杂度较高
无需填充,节省带宽 需处理多字节序问题
解析逻辑清晰 需确保长度字段完整接收

选择建议

  • 若数据长度固定 → 优先用固定长度协议
  • 若为文本协议且分隔符不会出现在数据中 → 用分隔符协议
  • 若需高效处理任意长度数据 → 用长度前缀协议(现代协议主流方案)
相关推荐
gadiaola13 分钟前
【计算机网络】第3章:传输层—面向连接的传输:TCP
网络·网络协议·tcp/ip·计算机网络
编程小白呀13 分钟前
【计算机网络】网络层协议
计算机网络
九转苍翎13 分钟前
计算机网络(5)——数据链路层
计算机网络·数据链路层
王火火(DDoS CC防护)3 小时前
UDP与TCP的区别是什么?
网络协议·tcp/ip·udp
Freeking10244 小时前
【计算机网络】HTTPS
网络协议·计算机网络·https
Elohim8154 小时前
网络编程之TCP编程
网络·tcp/ip·客户端和服务器端
hgdlip4 小时前
电脑为什么换个ip就上不了网了
网络·tcp/ip·电脑
weixin_478689764 小时前
【输入URL到页面展示】
tcp/ip·计算机网络
march of Time5 小时前
go的工具库:github.com/expr-lang/expr
开发语言·golang·github
遇见火星5 小时前
【运维实战】Rsync将一台主Web服务器上的文件和目录同步到另一台备份服务器!
运维·服务器·github·rsync