HTTP概述 01

HTTP 概述 - HTTP | MDN

1 TCP TLS

TCP - MDN Web 文档术语表:Web 相关术语的定义 | MDN

TCP(传输控制协议,Transmission Control Protocol) 是一个让两个主机相互连接并传输数据流的重要的网络协议

TCP 保证了数据和包以发送时的顺序的传输。Vint Cerf 和 Bob Kahn 在 1970 年代设计了 TCP,当时他们是 DARPA 科学家。

TCP 的作用是确保数据包的可靠传输和无误。TCP 实现了拥塞控制,这意味着初始请求从小开始,逐渐增加到计算机、服务器和网络可以支持的带宽水平。

【TCP连接怎么理解?就是一个网络通道协议吗,此路通行?】

可以把 TCP 连接理解成 "一条可靠的双向网络通道",它不仅是 "此路通行",还负责保障数据传输的 "可靠性" 和 "有序性",咱们可以用 "快递运输" 的类比来拆解:

1. 「通道建立」:先打电话确认路线

TCP 连接建立前 ,会通过**"三次握手"**确认双方能正常通信,就像你给快递站打电话:

  • 你(客户端):"喂,能发快递不?"(发送 SYN 包)
  • 快递站(服务器):"能发,你什么时候送过来?"(回复 SYN+ACK 包)
  • 你:"好的,我这就送!"(发送 ACK 包)三次交互后,"快递通道"(TCP 连接)就正式建立了,双方可以开始传数据。

2. 「数据传输」:每段快递都要签收

TCP 是可靠传输,就像快递每到一个中转站都要 "签收确认":

  • 你给商家寄包裹(发送数据段),会带一个 "序号"(比如第 1 段、第 2 段...)。
  • 商家收到后,会回一个 "确认号"(比如收到第 2 段,确认号是 3,表示接下来要收第 3 段)。
  • 如果某段包裹丢了(数据丢失),商家没回确认号,你就会重新发这段(重传机制)。这样就保证了数据不丢、不重复、有序到达

3. 「通道关闭」:用完通道要礼貌告别

数据传完后,TCP 连接会通过 "四次挥手" 关闭,就像挂电话前的道别:

  • 你:"我没数据要发了"(发送 FIN 包)
  • 商家:"收到,我看看还有没有数据要给你..."(回复 ACK 包,同时处理自己的剩余数据)
  • 商家:"我也没数据了"(发送 FIN 包)
  • 你:"收到,再见"(回复 ACK 包)这样双方就优雅地关闭了连接,避免 "占着通道不干活"。

对比:TCP 不是 "简单的通道",而是 "带保障的通道"

如果把网络协议分层理解:

  • IP 协议"普通公路",只负责把数据送到大致方向,不管丢不丢、乱不乱。
  • TCP 协议"带跟踪、签收、重发的快递专线",在 IP 的基础上,通过 "三次握手、序号确认、重传、四次挥手" 这些机制,保障数据可靠、有序地传输。

所以,TCP 不仅是 "此路通行",更是"可靠传输的保障协议",HTTP 等应用层协议正是基于 TCP 的可靠性,才能安全地传输网页、数据。

TLS - MDN Web 文档术语表:Web 相关术语的定义 | MDN

传输层安全性协议(Transport Layer Security,缩写作 TLS),前身安全套接层(Secure Sockets Layer,缩写作 SSL) ,是一个被应用程序用来在网络中安全通信的协议,防止电子邮件、网页、消息以及其他协议被篡改或是窃听。TLS 和 SSL 都是客户端/服务器协议,通过使用加密协议来提供网络安全。当服务器和客户端使用 TLS 通信时,它确保没有第三方可以窃听或篡改任何消息。

所有现代浏览器都支持 TLS 协议,它们都要求服务器提供一个有效的数字证书来确认身份以建立安全连接。如果客户端和服务器都能提供自己的数字证书,则它们可以互相认证。

2 HTTP无状态,但并非无会话

一、HTTP 是 "无状态" 的

"无状态" 指的是 HTTP 协议本身不会记录请求之间的关联

比如你在电商网站先浏览商品,再加入购物车,这两个操作对应的 HTTP 请求,在协议层面是 "独立" 的 ------ 服务器不会自动把 "浏览商品" 和 "加入购物车" 这两个行为关联到 "你" 这个用户身上。

这就像你去超市购物,每次结账时收银员都不记得你之前买过什么,每次都是 "新顾客",这就是 "无状态" 的直观体现。

因为 "无状态" 会导致用户在网站上无法进行连贯交互 (比如购物车记不住你加的商品、登录后刷新页面又要重新登录),所以需要一种技术来 "模拟" 有状态的会话即把多个请求关联到同一个用户身上 )。这个技术就是 HTTP Cookie

  • Cookie 的作用 :服务器可以在响应中给浏览器**"种"**一个 Cookie(类似一个带标识的小纸条),浏览器之后每次发请求都会带上这个 Cookie。
  • 会话的实现:比如你登录电商网站时,服务器给你发一个 Cookie(里面可能包含你的用户标识),之后你浏览商品、加购物车的请求都带着这个 Cookie,服务器就能通过 Cookie 识别出 "这些请求都是同一个用户发的",从而实现购物车记录、保持登录状态等 "有状态会话" 的效果。

简单总结:HTTP 协议本身不记事儿(无状态),但通过 Cookie 这个 "小纸条",可以让服务器和浏览器记住彼此的交互(有会话),从而实现像购物车、登录状态这样的连贯功能

3HTTP 的基本性质

1. 无状态性

如之前所讲,HTTP 协议本身不会记录请求之间的上下文关系,每个请求都是独立的。服务器不会自动关联不同请求所属的用户或操作,需借助 Cookie、Session 等技术来模拟有状态的会话。

2. 基于请求 - 响应模型

通信由客户端发起请求,服务器接收请求后返回响应。客户端(如浏览器)是请求的主动发起方,服务器是响应的被动提供方,遵循 "一问一答" 的模式。

3. 可扩展性

HTTP 协议的标头(Header)具有良好的扩展性。

除了自身定义的标头(如 Content-TypeCookie),还允许开发者自定义标头来传递额外信息,这也为 Cookie、各种 Web 技术(如 OAuth 认证)的集成提供了可能。

4. 支持多种方法

定义了多种请求方法来表示不同的操作意图,常见的有:

  • GET:用于获取资源,如浏览网页、查询数据。
  • POST:用于提交数据,如表单提交、创建资源。
  • PUT:用于更新资源(完整替换)。
  • DELETE:用于删除资源。
  • 还有 PATCH(部分更新资源)、HEAD(仅获取响应头)等方法。

5. 基于 TCP 协议

HTTP 通常基于 TCP 协议来保证数据传输的可靠性(TCP 是面向连接、可靠的传输层协议),默认使用端口 80(HTTP),加密的 HTTPS 则默认使用端口 443。

6. 媒体类型多样

支持传输多种类型的资源,通过 Content-Type 标头来标识,如文本(text/htmltext/plain)、图片(image/jpegimage/png)、音频视频(audio/mpegvideo/mp4)、应用程序数据(application/jsonapplication/xml)等。

4 HTTP 能控制什么

一、把每个 "控制项" 拆成 "生活场景 + 操作验证"

1. 缓存
  • 生活场景:你浏览新闻网站,第一次加载很慢,第二次打开却很快 ------ 这就是浏览器缓存了网页内容。
  • 操作验证 :打开浏览器(比如 Chrome),访问一个静态网页(如 https://example.com),然后按 F12 打开开发者工具,切到 "Network" 面板,刷新页面。找到对应请求的 "Response Headers",看看有没有 Cache-Control Expires 这些标头 ------ 这就是 HTTP 在控制缓存规则啦。

2. 同源限制(开放同源限制)
  • 生活场景:你在 A 网站想调用 B 网站的接口,浏览器直接拦截了 ------ 这是同源限制在保护你。但有些合法场景需要突破,比如前端调用微信支付接口,就需要通过 HTTP 标头来允许。
  • 操作验证 :写个简单的前端页面,尝试请求不同域名的接口(比如你本地起个服务,请求 https://api.github.com),会看到浏览器控制台报 "跨域" 错误。然后让后端在响应头里加 Access-Control-Allow-Origin: *,再试一次,请求就成功了 ------ 这就是 HTTP 控制同源限制的体现。
3. 认证
  • 生活场景:你登录某网站时,输入账号密码后,后续操作就不用反复输了 ------ 这是 HTTP 认证 + Cookie 在起作用。
  • 操作验证 :访问一个需要登录的网站(比如你的博客后台),输入账号密码后,看请求的 "Request Headers" 里有没有 Cookie 字段,响应头里有没有 Set-Cookie------ 这就是 HTTP 用 Cookie 维持认证会话的过程。

4. 代理服务器和隧道
  • 生活场景:公司内网里,你能上网是因为请求都通过公司的代理服务器转发;有些工具(如 VPN)用 HTTP 隧道穿透网络限制。
  • 操作验证 :在浏览器设置里配置一个代理(比如用 Fiddler 工具当代理),然后访问网页,在 Fiddler 里能看到所有 HTTP 请求都经过它 ------ 这就是代理服务器在工作。
5. 会话(Cookie 实现)
  • 生活场景:电商网站里你加了商品到购物车,关了浏览器再打开,购物车还在 ------ 这是 Cookie 帮你维持了会话。
  • 操作验证:访问电商网站,加个商品到购物车,然后看浏览器的 "Cookie" 管理界面(Chrome 里是 "设置 - 隐私和安全 - 网站设置 - Cookie 和其他站点数据"),能看到该网站的 Cookie 里存着购物车信息。

二、用 "工具 + 实践" 把理论落地

  1. 抓包工具直观看 HTTP 交互 :用 FiddlerWireshark 抓包,看看每次网页请求的请求头、响应头里都藏着哪些控制项(比如缓存标头、Cookie、认证标头)。
  2. 写简单服务端代码验证逻辑 :比如用 Python 的 Flask 框架,写一个接口,在响应头里加 Cache-Control: max-age=3600(控制缓存 1 小时),然后用浏览器访问,看缓存是否生效;再写一个接口,加 Set-Cookie: user=test,然后后续请求就能带上这个 Cookie。

5 HTTP 流

一、把 "HTTP 流四步" 拆成 "生活快递员送货" 类比

咱们把客户端(浏览器) 想象成 "你",服务器 想象成 "商家",TCP 连接 是 "快递通道",HTTP 报文是 "快递单 / 包裹":

1.打开 TCP 连接

类比:你给商家打电话(建立快递通道),可以打新电话(新建 TCP 连接)、用之前的电话(复用 TCP 连接),或者同时打多个电话(开多个 TCP 连接)。

直观操作: 打开浏览器开发者工具(F12)→ 切到 "网络" 面板 → 刷新页面,你会看到很多请求,这些请求可能共用一个 TCP 连接(看 "连接 ID" 是否重复)。

这两个请求的 "远程地址" 都是 192.168.101.252:443,说明它们复用了同一个 TCP 连接。

这里的 "远程地址" 就是服务器的 IP 地址和端口(443 是 HTTPS 的默认端口),相同的远程地址意味着这两个请求走的是同一条 TCP 通道,体现了 TCP 连接的复用机制。

2.发送 HTTP 报文(请求)

类比:你给商家发快递单,写清楚 "要什么商品(GET /)、寄到哪(Host: 域名)、要什么语言的说明(Accept-Language: zh)"。

直观操作: 在 "网络" 面板里选一个请求(比如首页的 GET 请求)→ 点 "标头"→ 看 "请求标头",就能看到和示例里一样的 GET / HTTP/1.1Host 这些字段。

3.读取服务端返回的报文(响应)

类比:商家收到快递单后,给你寄包裹,包裹上写着 "有没有货(200 OK)、什么时候发的(Date)、包裹多大(Content-Length)、是什么类型(Content-Type: text/html 就是网页)"。

直观操作: 还是看那个请求的 "标头"→ 切到 "响应标头",就能看到 HTTP/1.1 200 OKDateContent-Type 这些字段,和示例里的结构一模一样。

比如响应头里的 HTTP/1.1 200 OK 是响应报文的起始行,Content-Type Server 这些是响应头字段;请求头里的 GET /xxx 是请求起始行,Accept Cookie 这些是请求头字段 ------ 这完全符合 HTTP 报文的结构,所以这就是你能直观看到的 HTTP 报文内容。

4.关闭或复用连接

类比:如果还想买东西,就继续用这个快递通道(复用 TCP 连接);如果不买了,就挂电话(关闭连接)。

**直观操作:**在 "网络" 面板里看多个请求的 "连接 ID",如果重复,就是复用了连接;如果每次都不一样,就是新建 / 关闭后重建的。

二、用 "抓包工具 + 手动构造请求" 把理论落地

用浏览器开发者工具 "看真实的 HTTP 流"

随便打开一个网站(比如知乎),按 F12 打开开发者工具,切到 "网络" 面板,刷新页面。

然后任选一个请求,依次看 "请求标头""响应标头""响应内容",对应到 HTTP 流的 "发送请求→接收响应" 过程,每一个字段都能和理论对应上。

用工具手动发请求(模拟客户端)

装个工具叫 Postman(或用在线的 curl 工具),手动构造一个 GET 请求:

请求地址填 https://developer.mozilla.org

加个请求头 Accept-Language: zh然后发送,就能看到服务器返回的响应,和示例里的响应报文结构完全一致,这样就能直观理解 "请求 - 响应" 的交互了。

三、分版本对比(HTTP/1.1 vs HTTP/2)

如果觉得 "HTTP 流水线""帧的多路复用" 抽象,可以这么对比:

HTTP/1.1:像 "排队长队",一个请求处理完才能发下一个(流水线想优化但没普及开)。

HTTP/2:像 "超市多收银台",多个请求可以打包成 "帧" 同时发,服务器也能同时处理(这就是 "多路复用")。

直观操作: 找个支持 HTTP/2 的网站(比如淘宝),看 "网络" 面板里的请求,会发现多个请求的 "协议" 列显示 h2,而且它们的 "发起时间" 很接近 ------ 这就是 HTTP/2 多路复用的体现。

总结一下:先把每一步和生活场景绑定,再用工具看真实的请求响应,最后对比不同版本的差异,这样抽象的理论就会变得特别具体!

6 HTTP 报文

HTTP 报文是 HTTP 协议中客户端与服务器之间传递信息的格式载体 ,分为请求报文响应报文两类,下面从结构、组成部分、示例等维度详细介绍:

一、HTTP 报文的基本结构

HTTP 报文由起始行头部(Header)空行和 ** 主体(Body,可选)** 四部分组成,结构如下:

bash 复制代码
[起始行]
[头部字段1]: 值
[头部字段2]: 值
...
[空行]
[主体内容(如HTML、JSON、图片等)]

二、请求报文(客户端→服务器)

请求报文是客户端向服务器发起请求时发送的报文,核心组成如下:

1. 起始行(请求行)

格式:请求方法 请求路径 HTTP版本

  • 请求方法 :表示操作意图,如 GET(获取资源)、POST(提交数据)、PUT(更新资源)、DELETE(删除资源)等。
  • 请求路径 :资源在服务器上的路径,如 /index.html/api/data
  • HTTP 版本 :如 HTTP/1.1HTTP/2

示例:GET /sopplus_web/customized/es/selfWords.jsp?p=YXM9MiZ0I=jsonp31762951556027 HTTP/1.1

2. 头部字段(请求头)

用于传递额外信息,常见字段:

  • Host:指定服务器域名和端口,如 Host: i.hdu.edu.cn
  • Accept:客户端可接受的资源类型,如 Accept: text/html,application/json
  • Cookie:携带客户端的 Cookie 信息,用于身份识别或会话保持。
  • User-Agent:客户端的设备、浏览器信息,如 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/119.0.0.0
3. 主体(请求体,可选)

仅在 POSTPUT 等方法中存在,用于提交数据(如表单、JSON 数据)。示例(POST 提交 JSON):

bash 复制代码
{
  "username": "test",
  "password": "123456"
}

三、响应报文(服务器→客户端)

响应报文是服务器对客户端请求的回复,核心组成如下:

1. 起始行(状态行)

格式:HTTP版本 状态码 状态描述

  • HTTP 版本 :与请求报文的版本一致,如 HTTP/1.1
  • 状态码 :三位数字表示响应结果,如 200(成功)、404(资源未找到)、500(服务器内部错误)。
  • 状态描述 :对状态码的文字说明,如 OKNot Found

示例:HTTP/1.1 200 OK

2. 头部字段(响应头)

传递服务器的额外信息,常见字段:

  • Content-Type:响应主体的类型,如 text/html(网页)、application/json(JSON 数据)、image/png(图片)。
  • Content-Length:响应主体的字节长度。
  • Set-Cookie:服务器向客户端设置 Cookie。
  • Server:服务器的软件类型,如 Server: nginx/1.25.1
  • Date:响应生成的时间。
3. 主体(响应体,可选)

包含服务器返回的实际资源(如网页内容、数据、图片等)。示例(HTML 响应体):

html 复制代码
<!DOCTYPE html>
<html>
  <head><title>示例页面</title></head>
  <body>Hello, HTTP!</body>
</html>

四、HTTP 报文的可读性与传输

  • 可读性 :HTTP/1.1 及之前的报文是明文可读的(如你在浏览器开发者工具中看到的原始报文);HTTP/2 及之后的报文会被封装成 "帧" 并二进制编码,不可直接读取,但逻辑结构与 HTTP/1.1 一致。
  • 传输载体:HTTP 报文基于 TCP 连接传输,请求和响应的交互过程依赖 TCP 保障可靠性。

通过理解 HTTP 报文的结构和字段,你可以清晰地分析客户端与服务器之间的通信细节,这也是排查网络问题、理解 Web 交互的关键基础。

7 基于 HTTP 的 API

一、Fetch API:"主动问服务器要东西"(你→服务器)

生活场景

就像你给奶茶店打电话:"麻烦送一杯珍珠奶茶"(你主动要),奶茶店说好(响应),挂电话(结束)。

代码示例(浏览器控制台直接跑)

比如你想从服务器要一份用户数据:

javascript 复制代码
// 打电话给服务器:"我要 /users 这个数据"
fetch('/users')
  .then(response => response.json()) // 解析奶茶(数据)
  .then(data => {
    console.log('拿到的数据:', data); // 打印:[{name: '张三'}, ...]
  });
  • 特点:你主动发起,一次请求对应一次回复,完事就断联。
  • 用途:刷网页、点详情、提交表单(比如你点 "登录",就是用类似代码把账号密码发给服务器)。

二、XMLHttpRequest(XHR):"老式电话问奶茶"(旧版主动要)

生活场景

和上面一样,但用的是 "转盘电话",步骤多一点:先摇转盘(初始化),再拨号(打开连接),再说话(发送请求)。

代码示例
javascript 复制代码
// 摇转盘(创建XHR对象)
const xhr = new XMLHttpRequest();
// 拨号(打开连接:方法是GET,地址是/users)
xhr.open('GET', '/users');
// 等对方回应(监听状态变化)
xhr.onload = function() {
  if (xhr.status === 200) {
    const data = JSON.parse(xhr.responseText); // 解析数据
    console.log('拿到的数据:', data);
  }
};
// 说话(发送请求)
xhr.send();
  • 特点:功能和 Fetch 一样,但写法麻烦,现在基本被 Fetch 取代(就像转盘电话被智能手机取代)。

三、Server-sent 事件:"奶茶店主动喊你取餐"(服务器→你)

生活场景

你在奶茶店小程序下单后,店员说 "做好了喊你"(建立长连接),等做好了就喊你(服务器推送消息),你不用一直问。

代码示例(客户端 + 服务器极简版)

客户端(浏览器)

javascript 复制代码
// 告诉服务器:"做好了喊我,地址是 /notify"
const eventSource = new EventSource('/notify');

// 听到喊"你的奶茶好了"(监听消息)
eventSource.onmessage = function(event) {
  console.log('服务器喊你:', event.data); // 打印:"你的奶茶好了,来取!"
};

服务器(简单 Node.js 示例)

javascript 复制代码
// 服务器端代码:每5秒喊一次
app.get('/notify', (req, res) => {
  res.setHeader('Content-Type', 'text/event-stream');
  setInterval(() => {
    res.write(`data: 你的奶茶还在做...\n\n`); // 推消息给客户端
  }, 5000);
});
  • 特点:服务器单方面一直发,你只负责收,连接一直保持(直到你离开奶茶店)。
  • 用途:实时通知(比如 "有人给你点赞了""订单发货了")。

四、WebSocket:"和奶茶店开对讲机"(双向随时聊)

生活场景

你和奶茶店开了对讲机,你可以问 "我的奶茶放糖了吗"(你→服务器),店员也能随时说 "不好意思,珍珠没了,换椰果行吗"(服务器→你)。

代码示例(客户端 + 服务器)

客户端(浏览器):运行

javascript 复制代码
// 打开对讲机(通过HTTP握手建立连接)
const socket = new WebSocket('ws://localhost:3000');

// 收到对讲机消息(服务器发来的)
socket.onmessage = function(event) {
  console.log('店员说:', event.data); // 打印:"珍珠没了,换椰果?"
};

// 对着对讲机说话(发给服务器)
socket.send('好的,换椰果!');

服务器(Node.js 用 ws 库)

javascript 复制代码
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3000 });

wss.on('connection', (ws) => {
  // 收到客户端消息
  ws.on('message', (message) => {
    console.log('顾客说:', message); // 打印:"好的,换椰果!"
  });
  // 给客户端发消息
  ws.send('珍珠没了,换椰果行吗?');
});
  • 特点:双向实时聊,连接一直保持,适合需要频繁互动的场景。
  • 用途:网页聊天、多人在线游戏(比如你移动角色,其他人能立刻看到)。

一句话总结

  • Fetch/XHR:你问一句,服务器答一句(单次互动)。
  • Server-sent:服务器一直给你报信,你不用问(单向持续)。
  • WebSocket:你和服务器随时互聊(双向持续)。

试着把代码复制到自己的项目里跑一跑,看到控制台输出的那一刻,就再也不抽象啦!

相关推荐
思茂信息2 小时前
CST电动车EMC仿真(二)——电机控制器MCU的EMC仿真
开发语言·javascript·单片机·嵌入式硬件·cst·电磁仿真
ManageEngine卓豪2 小时前
如何在IIS中配置HTTP重定向
http·iis·http重定向
John_Rey2 小时前
API 设计哲学:构建健壮、易用且符合惯用语的 Rust 库
网络·算法·rust
晴殇i2 小时前
前端极速性能优化:从加载到渲染的全链路实战指南
前端·javascript
Tonya432 小时前
测开学习DAY27
学习
AAA阿giao2 小时前
JavaScript 深拷贝全解析:从栈与堆内存机制到安全对象复制实践
前端·javascript·json
AAA阿giao2 小时前
深入理解 JavaScript 的 Array.prototype.map() 方法及其经典陷阱:从原理到面试实战
前端·javascript·面试
笨鸟笃行2 小时前
百日挑战——单词篇(第二十天)
学习
大公产经晚间消息2 小时前
网易云音乐回应“不适配鸿蒙”:推动相关部门加快步伐
网络