前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • HTTP

    • 基础篇

      • HTTP的前世今生
      • HTTP是什么
      • HTTP世界全览
      • HTTP分层
      • 键入网址到回车发生什么
      • HTTP报文是什么样子的
      • 理解请求方法
      • URI
      • 响应状态码
      • HTTP有哪些特点
      • HTTP优缺点
      • HTTP的实体数据
      • HTTP传输大文件
      • HTTP的连接管理
      • HTTP的重定向
      • HTTP的Cookie机制
      • HTTP的缓存控制
      • HTTP的代理服务
      • HTTP的缓存代理
    • 高级篇

    • 扩展篇

  • 浏览器相关

  • 计算机基础

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

TCP协议:如何保证页面文件能被完整送达浏览器|浏览器篇

# TCP协议:如何保证页面文件能被完整送达浏览器

30 秒速记

  • FP 表示从页面开始加载到首次绘制的耗时,网络加载速度是其重要影响因素之一。
  • 页面文件不会天然作为一个整体可靠到达,而是会被拆成多个数据包传输。
  • 数据包在网络途中可能丢失或出错,因此完整送达需要网络协议提供保障。
  • HTTP 和 WebSocket 都建立在 TCP/IP 体系之上,理解底层协议有助于分析加载性能和网络故障。
  • 给定材料只提出 TCP 如何保证完整性的核心问题,未展开确认、重传或排序等具体机制。

TCP 通过序列号、确认与重传等机制,保证页面数据以可靠、有序的字节流交给浏览器。 数据在网络中会被拆成多个段,接收端根据序列号还原顺序并发现缺口,发送端则在超时或收到丢包信号后重传。校验和用于发现传输错误,流量控制和拥塞控制用于限制发送节奏。需要注意,TCP 不保留应用的写入边界,也不保证连接中断后业务一定处理成功;HTTP/3 的可靠性则由基于 UDP 的 QUIC 提供。

在衡量Web页面性能的时候有一个重要的指标叫“FP(First Paint)”,是指从页面加载到首次开始绘制的时长。这个指标直接影响了用户的跳出率,更快的页面响应意味着更多的PV、更高的参与度,以及更高的转化率。那什么影响FP指标呢?其中一个重要的因素是网络加载速度

要想优化Web页面的加载速度,你需要对网络有充分的了解。而理解网络的关键是要对网络协议有深刻的认识,不管你是使用HTTP,还是使用WebSocket,它们都是基于TCP/IP的,如果你对这些原理有足够了解,也就清楚如何去优化Web性能,或者能更轻松地定位Web问题了。此外,TCP/IP的设计思想还有助于拓宽你的知识边界,从而在整体上提升你对项目的理解和解决问题的能力。

好,接下来我们回到正题,开始今天的内容。在网络中,一个文件通常会被拆分为很多数据包来进行传输,而数据包在传输过程中又有很大概率丢失或者出错。那么如何保证页面文件能被完整地送达浏览器呢?

这篇文章将站在数据包的视角,给出问题答案

原理拆解: 应用写入的一段页面数据会被 TCP 拆成适合传输的字节段。接收端利用序列号恢复字节顺序并识别缺口,通过确认信息告知已收到的范围;发送端在超时或其他丢包信号出现时重传缺失数据。校验和用于发现传输错误,滑动窗口控制未确认数据量,拥塞控制则避免持续向拥塞链路注入过多数据。只有连续、已确认的字节才能按序交给应用,因此 HTTP 获得的是可靠字节流,而不是天然保留发送次数边界的“消息包”。

最小验证: 输入是客户端分三次写入的 UTF-8 页面内容,要验证的结论是:服务端读取到的 data 事件次数不可假定,但拼接后的字节流与原内容一致。将代码保存为 tcp.js,使用 node tcp.js 运行。

const net = require('node:net');

const expected = '<h1>TCP 保持字节顺序</h1>';
const server = net.createServer(socket => {
  const chunks = [];
  socket.on('data', chunk => chunks.push(chunk));
  socket.on('end', () => {
    const received = Buffer.concat(chunks).toString('utf8');
    console.log({ dataEvents: chunks.length, received });
    console.log('完整且有序:', received === expected);
    server.close();
  });
});

server.listen(0, '127.0.0.1', () => {
  const { port } = server.address();
  const client = net.createConnection({ port, host: '127.0.0.1' }, () => {
    client.write('<h1>');
    client.write('TCP 保持字节顺序');
    client.end('</h1>');
  });
});
@前端进阶之旅: 代码已经复制到剪贴板

关键行是 Buffer.concat(chunks):应用必须按字节流累积数据,不能把一次 data 回调等同于一次 write。预期最后输出 完整且有序: true;dataEvents 的值由系统缓冲和调度决定,可能不是 3。本机测试不会制造真实丢包,也无法直接观察重传。

边界与排查: TCP 保障连接内字节的可靠、有序交付,却不保证请求一定被业务处理,也不保证无限等待后必然成功;连接中断、超时和进程崩溃仍需应用处理。排查线上问题可结合浏览器网络面板、服务端日志和抓包,区分 DNS、建连、重传与应用响应耗时。经典 HTTP/1.1、HTTP/2 和 WebSocket 通常使用 TCP;HTTP/3 使用基于 UDP 的 QUIC,可靠性由 QUIC 自身实现。

面试官追问

追问 1服务端连续调用三次 socket.write 发送一段页面,客户端只触发一次 data,同事据此判断丢了两个包,你怎么纠正?
参考回答

一次 data 回调不能对应一次 write,只触发一次回调并不能证明发生丢包。TCP 向应用提供可靠、有序的字节流,系统可能合并或拆分读取结果;应用应累积字节并按自身协议解析,不能依赖回调次数保存消息边界。

追问 2你要验证一段 UTF-8 页面经过 TCP 后是否完整,服务端代码应该检查什么,而不是统计 data 事件次数?
参考回答

服务端应收集各次收到的 Buffer,在连接结束或满足应用协议边界后通过 Buffer.concat 拼接,再与预期字节内容比较。事件次数受缓冲和调度影响,不能作为完整性依据;本机验证也无法证明公网中没有重传或连接中断。

追问 3接口负责人说 TCP 已保证可靠传输,所以订单请求不需要超时、重试或幂等处理,你会怎么回应?
参考回答

TCP 只保证连接内字节可靠、有序交付,不保证请求一定被业务处理,也不保证无限等待后必然成功。连接中断、进程崩溃或响应超时仍需应用处理;贸然重试还可能造成重复业务操作,因此必须结合幂等或去重机制。

追问 4线上首页偶发加载慢,抓包看到重传,同时服务端接口也有长尾耗时,你会怎样拆分责任边界?
参考回答

应结合浏览器网络面板、服务端日志和抓包,分别核对 DNS、建连、重传以及应用响应耗时。重传能说明传输链路存在丢包信号,却不能证明全部延迟都由网络造成;若服务端处理同样缓慢,还需独立定位应用阶段。

追问 5新站点在 HTTP/2 与 HTTP/3 间选型,评审者声称两者的可靠传输都直接由 TCP 提供,你如何修正?
参考回答

经典 HTTP/2 通常运行在 TCP 上,其字节可靠性由 TCP 提供;HTTP/3 则使用基于 UDP 的 QUIC,可靠机制由 QUIC 自身实现。选型时不能把两者的传输层行为混为一谈,也不能仅凭协议名称推断实际性能收益。

追问 6监控显示 FP 升高且下载耗时变长,业务方要求直接扩容前端服务器,你会先验证哪些相邻环节?
参考回答

网络加载速度确实会影响 FP,但它只是首绘耗时的重要因素之一,不能据此直接归因服务器容量。应拆分连接、传输、应用响应及浏览器渲染时间,再确认瓶颈位置;扩容只能改善匹配的服务端瓶颈,无法修复链路重传或渲染阻塞。

# 一个数据包的“旅程”

30 秒速记

  • 互联网由通信理念与协议体系共同构成,协议负责规定参与方一致遵守的通信规则。
  • 网络传输的基本载体是数据包,而不是默认一次发送完整的大文件。
  • 数据量较大时,内容会被拆分成多个较小的数据包分别传输。
  • 理解一次传输需要区分三个问题:数据包怎样到达目标主机、主机怎样交给目标应用、应用怎样获得完整数据。
  • 给定材料仅建立分层分析框架,没有说明每一层采用的具体协议机制。

一个数据包的传输,要分别解决送到哪台主机、交给哪个应用,以及如何还原完整数据这三个问题。 网络层依据目标 IP 负责跨节点寻址,端口用于找到目标进程,传输层再按所用协议处理顺序与可靠性。比如浏览器下载较大的页面文件时,内容会拆成多个包,它们可能经历不同延迟甚至丢失。包到达主机不等于页面已完整交付,排查时也要分别检查地址可达性、端口监听和丢包重传情况。

下面我将分别从“数据包如何送达主机”“主机如何将数据包转交给应用”和“数据是如何被完整地送达应用程序”这三个角度来为你讲述数据的传输过程

互联网,实际上是一套理念和协议组成的体系架构。其中,协议是一套众所周知的规则和标准,如果各方都同意使用,那么它们之间的通信将变得毫无障碍

互联网中的数据是通过数据包来传输的。如果发送的数据很大,那么该数据就会被拆分为很多小数据包来传输。比如你现在听的音频数据,是拆分成一个个小的数据包来传输的,并不是一个大的文件一次传输过来的

原理拆解: 一次网络传输可以沿分层链路理解。发送端应用先产生内容,传输层负责标识通信应用,并按所用协议提供相应的传输能力;网络层根据目标 IP 地址把数据包送往目标主机。数据经过多个中间节点后到达接收端,再按照相反方向逐层解封装,最终交给目标应用。分层的价值在于职责隔离:路由设备通常只需关心如何转发,应用也无须理解每一跳的物理传输细节。

具体例子: 浏览器获取一个较大的页面文件时,文件不会作为不可分割的整体穿过网络,而会形成多个数据包。每个包可能经过不同队列、产生不同延迟,甚至出现丢失。目标主机只回答了“包到了哪台机器”,端口信息才回答“交给哪个进程”,至于能否恢复成完整、顺序正确的内容,则取决于传输层协议提供的机制。

边界与排查: “已经到达主机”不等于“浏览器已经收到完整页面”。路由可达但端口未监听时,应用仍无法接收;部分包到达但其余包丢失时,内容也不能直接视为完整。排查时应依次验证目标地址是否可达、目标端口是否由正确进程监听、传输层是否发生丢包或重传,以及应用是否成功消费数据。抓包工具可以观察封装字段和包的先后关系,但仅凭单个数据包无法证明整个文件已经完整交付。

← Chrome架构:仅仅打开了1个页面,为什么有4个进程HTTP请求流程:为什么很多站点第二次打开速度会很快 →

fe
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • HTTP

    • 基础篇

      • HTTP的前世今生
      • HTTP是什么
      • HTTP世界全览
      • HTTP分层
      • 键入网址到回车发生什么
      • HTTP报文是什么样子的
      • 理解请求方法
      • URI
      • 响应状态码
      • HTTP有哪些特点
      • HTTP优缺点
      • HTTP的实体数据
      • HTTP传输大文件
      • HTTP的连接管理
      • HTTP的重定向
      • HTTP的Cookie机制
      • HTTP的缓存控制
      • HTTP的代理服务
      • HTTP的缓存代理
    • 高级篇

    • 扩展篇

  • 浏览器相关

  • 计算机基础