当前位置: 首页 > news >正文

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

目录

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

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

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

TCP 为什么可靠?

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

2. 超时重传(Retransmission)

3. 滑动窗口(Sliding Window)

4. 拥塞控制(Congestion Control)

5. 校验和(Checksum)

6. 面向连接

总结对比

TCP滑动窗口

三次握手期间的窗口协商

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

关键细节补充 

1. 窗口大小与拥塞控制的关系

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

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 → ACKFIN → ACK → FIN → ACK序列号、ACK、重传、窗口、校验和
状态转换CLOSED → SYN_SENT → ESTABLISHEDESTABLISHED → 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有什么区别

核心设计目标
TCPUDP
面向连接:通过三次握手建立连接,四次挥手关闭连接,确保通信双方状态同步。无连接:无需建立连接,直接发送数据,资源开销小。
可靠传输:确保数据准确、有序到达,通过序列号、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报文结构

指标TCPUDP
传输效率低(头部开销大,需维护连接状态)高(头部仅 8 字节,无连接开销)
实时性低(重传、排序等引入延迟)高(无重传,延迟小)
吞吐量稳定(拥塞控制避免网络崩溃)不稳定(可能因网络拥塞丢包)
资源占用高(需维护连接状态表)低(无连接状态)
典型应用场景
场景TCP 适用UDP 适用
Web 浏览(HTTP)✅ 需可靠传输,避免页面错乱❌ 不可靠传输可能导致页面缺失
文件传输(FTP)✅ 确保文件完整无误❌ 丢包会导致文件损坏
电子邮件(SMTP)✅ 邮件内容必须完整送达❌ 不可靠传输会导致邮件丢失
实时音视频❌ 重传会加剧延迟,影响体验✅ 容忍少量丢包,优先保证实时性
DNS 查询❌ 单次查询延迟高(需握手)✅ 快速响应,少量丢包可重试
游戏联机❌ 角色位置同步需低延迟✅ 允许少量预测误差,优先流畅性
可靠性机制对比
机制TCPUDP
连接管理三次握手建立连接,四次挥手关闭无连接过程
序列号与 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. 接收方先读取长度字段,再按长度读取完整数据。
优点缺点
高效处理任意长度数据实现复杂度较高
无需填充,节省带宽需处理多字节序问题
解析逻辑清晰需确保长度字段完整接收

选择建议

  • 若数据长度固定 → 优先用固定长度协议
  • 若为文本协议且分隔符不会出现在数据中 → 用分隔符协议
  • 若需高效处理任意长度数据 → 用长度前缀协议(现代协议主流方案)

相关文章:

  • 邂逅Webpack和打包过程
  • 十四、【测试执行篇】让测试跑起来:API 接口测试执行器设计与实现 (后端执行逻辑)
  • 基于springboot的益智游戏系统的设计与实现
  • 安全漏洞修复导致SpringBoot2.7与Springfox不兼容
  • Excel to JSON 插件 2.4.0 版本更新
  • Docker Compose(容器编排)
  • 在Mathematica中可视化Root和Log函数
  • android lifeCycleOwner生命周期
  • vue3中的ref和reactive
  • vim 的基本使用
  • vue+mitt的简便使用
  • Linux 简单模拟实现C语言文件流
  • 剑指offer13_剪绳子
  • [Protobuf]常见数据类型以及使用注意事项
  • MacroDroid安卓版:自动化操作,让生活更智能
  • Android第十一次面试补充篇
  • 力扣题解106:从中序与后序遍历序列构造二叉树
  • 雪花算法:分布式ID生成的优雅解决方案
  • LINUX 61 rsync定时同步;软链接
  • RAGflow详解及实战指南
  • html5网站尺寸/网推
  • 石家庄网站制作工具/百度问答入口
  • 重庆网站制作公司/seo优化专员招聘
  • 陕西建设厅网站人才库/正规的培训机构有哪些
  • 广安网站建设哪家好/百度网页版主页
  • 北京最新疫情消息今天/学seo需要学什么专业