🌐 HTTP 协议与网络请求深度解析笔记
核心结论:浏览器访问网站,本质上就是:DNS解析域名为 IP $\rightarrow$ 建立 TCP 连接 $\rightarrow$ 发送包含 Host 的 HTTP 请求 $\rightarrow$ 接收并解析 HTTP 响应。
1. 网络请求完整流程图解
以访问 [https://www.baidu.com/](https://www.baidu.com/) 为例:
【阶段一:地址解析】
用户输入 www.baidu.com
│
▼
DNS 查询 ───► 将 "www.baidu.com" 解析为 IP: "36.152.44.132"
│
【阶段二:建立连接】
▼
TCP 三次握手 ───► 向 36.152.44.132:443 发起 TCP 连接
│
【阶段三:发送请求】
▼
发送 HTTP 请求 ───► GET / HTTP/1.1
Host: www.baidu.com (告诉服务器具体访问哪个站点)
User-Agent: Chrome...
│
【阶段四:接收响应】
▼
接收 HTTP 响应 ───► HTTP/1.1 200 OK
Content-Type: text/html
<!DOCTYPE html>... (HTML/JSON 响应体)
2. 核心概念辨析:Host vs DNS vs 域名
| 概念 | 形象比喻 | 协议/技术层 | 本质与作用 | 发生时机 |
|---|---|---|---|---|
| DNS | 电话簿/查号台 | DNS 协议 | 将域名翻译成 IP 地址的服务 | TCP 连接之前 |
| 域名 (Domain) | 某人的名字 | 网络标识 | 服务器的具体名字(如 [www.baidu.com](https://www.baidu.com)) |
贯穿全程 |
| Host 字段 | 快递单上的“收件人”栏 | HTTP 协议 | HTTP 请求头中的一个标准 key,其 value 是域名 | TCP 连接之后 |
3. 为什么连接建立后还需要 Host 头?
核心原因:虚拟主机(一机多站)
同一台物理服务器(同一个 IP 地址)上,通常会托管成百上千个不同的网站:
服务器 IP: 36.152.44.132
├── www.baidu.com (百度主页)
├── tieba.baidu.com (百度贴吧)
└── zhidao.baidu.com (百度知道)
- TCP 连接(IP):只保证了你的数据包送达了“36.152.44.132 这台服务器大楼”。
- HTTP Host 头:明确告知服务器大楼的前台:“我要找的是 www.baidu.com 这个部门/网站”。
⚠️ 注意:如果缺少
Host头,服务器无法判断你要获取哪个网站的资源,通常会返回400 Bad Request或404 Not Found。
4. HTTP 响应报文与请求报文解构
🟢 响应报文(服务器返回)
以百度响应头为例:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Server: BWS/1.1
HTTP/1.1 200 OK:状态码,200代表请求成功;404代表页面未找到。Content-Type:告知接收方内容类型及字符集(如网页为text/html,天气接口为application/json)。Content-Encoding: gzip:启用数据压缩传输,降低网络流量。Server:服务器软件标识(Baidu Web Server)。
🔵 请求报文(客户端发送)
GET / HTTP/1.1
Host: www.baidu.com
User-Agent: Mozilla/5.0 ...
Accept: text/html,application/json
Accept-Language: zh-CN,zh;q=0.9
GET / HTTP/1.1:请求方法为GET,请求路径为根目录/,协议版本为HTTP/1.1。Host: [www.baidu.com](https://www.baidu.com):目标域名(必需项)。User-Agent:客户端身份标识(告知服务器是 Chrome、Safari 还是 ESP8266)。Accept:告知服务器客户端期望接收的数据格式。
5. HTTP请求头详解
HTTP头就是HTTP请求/响应中最前面的那些说明信息,就像快递包裹上的面单——告诉接收方"这是什么、从哪来、到哪去、怎么处理"。
| 头部字段 | 作用 | 快递比喻 |
|---|---|---|
GET /weather... HTTP/1.1 |
请求行:告诉服务器“我要什么、用什么协议” | “我要取件,用的是标准流程” |
Host: api.seniverse.com |
必须:告诉服务器要访问哪个网站(因为一个 IP 可能托管多个网站) | “我要去 A 栋楼(即使整栋楼都是快递公司)” |
User-Agent: ESP8266 |
告诉服务器“我是谁”(设备类型) | “我是一个小单片机在访问” |
Connection: close |
重要:告诉服务器“传完数据就断开连接” | “取完件就关门,不用等我下次” |
Accept: application/json |
告诉服务器“我能接收 JSON 格式数据” | “我只收这种格式的包裹” |
6. 浏览器 vs ESP8266 请求头差异
请求头不是固定不变的“默认值”,而是根据环境动态变化的:
| 特性 | 浏览器 (Chrome/Edge) | ESP8266 (手动 AT+CIPSEND) | ESP8266 (AT+HTTPCLIENT) |
|---|---|---|---|
| 头信息丰富度 | 非常丰富,包含动态 Cookie、语言、编码 | 极简,通常只有 Host 与 Connection |
包含固定的基本头 |
| 动态身份认证 | 自动携带 Cookie / Session | 需要手动硬编码加入 | 需要手动配置参数 |
| 数据接收类型 | 根据页面需求自动调整 Accept |
无限制,接收原始 Socket 数据 | 自动解析 HTTP 报文 |
7. ESP8266 GET请求 代码解析
AT+HTTPCLIENT=1,0 里的 1 和 0 分别代表 HTTP 请求方法和数据类型。AT+HTTPCLIENT=2,1 可以这样写,但含义完全不同了。
- 参数 1 (
):HTTP 请求方法
这个参数告诉 ESP8266 要对服务器执行什么操作。
1:代表 HEAD 请求,只获取服务器返回的响应头,不获取具体数据。
2:代表 GET 请求,用于从服务器获取数据,这也是你获取天气数据最常用的方法。
3:代表 POST 请求,用于向服务器提交数据。
- 参数 0 (
):数据类型
这个参数用于告知服务器,你发送的请求数据的格式是什么。
0:对应 application/x-www-form-urlencoded,是HTML表单默认的数据格式。
1:对应 application/json,表示你发送的数据是JSON格式。
- Q:能写成 AT+HTTPCLIENT=2,1 吗?
- A:完全可以。这条指令的含义变成了:
执行一个 GET 请求,并且以 application/json 格式告诉服务器我期望的数据类型。
举两个例子,区别就很清楚了:
获取天气(使用你的格式 AT+HTTPCLIENT=1,0):这里是 1 表示 HEAD 请求,所以我们并不建议用它获取天气数据。
获取天气(改为 GET 请求):如果改为 AT+HTTPCLIENT=2,0,...,才是真正开始获取天气数据了。
JSON数据交互:如果你的设备需要和服务器进行复杂的JSON数据交互,AT+HTTPCLIENT=2,1,... 就是正确的用法。
8. 终极映射:ESP8266 AT 指令对比
将浏览器在底层的操作映射到 ESP8266 的开发场景:
| 浏览器/底层网络行为 | ESP8266 手动模式 (AT+CIPSEND) | ESP8266 自动模式 (AT+HTTPCLIENT) |
|---|---|---|
| 1. DNS 解析 + TCP 连接 | AT+CIPSTART="TCP","api.seniverse.com",80 |
(内部自动完成) |
| 2. 准备发送 HTTP 请求 | AT+CIPSEND=... |
(内部自动完成) |
| 3. 发送请求行与 Host 头 | 发送: |
GET /v3/weather/now.json... HTTP/1.1\r\n
Host: api.seniverse.com\r\n\r\n | AT+HTTPCLIENT=2,0,"[http://api.seniverse.com/v3/](http://api.seniverse.com/v3/)..." |
| 4. 接收与解析响应 | 串口接收原始字符串,需手动提取响应体 JSON | 固件自动剥离 HTTP 响应头,直接提取数据 |
💡 总结口诀:
DNS 查 IP,TCP 建通路;Host 选站点,GET 拿数据。

浙公网安备 33010602011771号