联网与通信

第 22 课:HTTP 请求——板子去访问网页

板子当客户端去访问外部服务器,看懂状态码和返回的那堆文本

我是吴老师。这节课跟上一节正好反过来。

上一节课,板子是服务器——它开着热点坐在那儿,等别人来访问它,你的手机是客人,上门敲门。这节课,板子变成客户端——它自己出门,去访问别人。 上一节它答话,这一节它问话。同一件事的两面,你两节都摸过了,这件事才算真的懂。

而且今天你问的是外面世界的东西。前面所有的实验,板子都只在你的桌子上自娱自乐——它读的是你房间里的光、你桌上的温度、你手边的距离。从这一课起,它读到的是真实世界的数据。

一、客户端和服务器,到底谁是谁

这两个词你肯定听过,但我得给你说准了,因为很多人学了好几年还是含含糊糊的。别从"谁厉害"去理解,从"谁主动"去理解。

谁主动 干什么 例子
客户端 主动去问 发起请求,等答案 你的浏览器、你的板子
服务器 等着被问 收到请求,给答案 网站的后台、上一课的板子

服务器的特点不是"强大",是"一直开着、随时等着"。

你现在正在用的东西——浏览器——就是个客户端。你在地址栏敲一个网址回车,浏览器就替你去问了一趟,把答案拿回来画在屏幕上。你的板子今天要干的事,跟浏览器一模一样。 只不过浏览器会把答案"画"成漂亮的网页,而板子只会把答案原样打印出来——这个差别很重要,第五节专门讲。

二、一次 HTTP 请求长什么样

这个"你问我答"的过程有个正式名字叫 HTTP别被这三个字母吓到,它就是"客户端和服务器之间对话的一套规矩"。 规矩很简单,一来一回:

板子作为客户端主动发出 HTTP 请求,服务器回一段文本和状态码,200 表示成功、404 表示找不到、500 表示服务器出错

① 客户端先开口,说清楚"我要什么"。这一句叫请求② 服务器答一句,把结果送回来。这一句叫响应

就这两步。 没有第三步,没有握手,没有寒暄。HTTP 是一场特别公事公办的对话。

注意这个顺序:永远是客户端先开口。 服务器不会主动找你说话,它只会坐在那儿等。这一点你记住,第 24 课 ESP-NOW 你会看到"主动推"和"等着被问"的区别。

三、GET 和 POST:一个去取,一个去寄

请求分两种,名字看着眼生,其实特别好懂。

GET 像去取快递,报个单号就行,参数挂在网址后面看得见;POST 像寄包裹,东西装在请求体里一起送过去,外面看不见

我给你打个比方,你一下就能记住。GET = 去取快递。 你走到快递柜前面,报一个单号,柜子把东西给你——你是去"拿"东西的,报个号就行。POST = 寄一个包裹。 你抱着一个箱子去快递点,东西要跟着你一起送过去——你交出去的不只是"我来寄个东西"这句话,还有一个实实在在的包裹。

对应到代码里:

GET POST
干什么 我要拿点什么 我要提交点什么
参数放哪 拼在网址后面 装在"请求体"里
长什么样 ?city=beijing&day=2 藏在请求里面,地址栏看不见
什么时候用 查天气、取数据、读状态 提交表单、上传数据、登录

最后一行那个区别有个很实际的后果:GET 的参数是露在外面的,所以绝对不能拿它传密码。 你想想,密码写在地址栏里,截图发出去、浏览器历史记录留着、路由器日志记着——全漏了。该用 POST 的时候用 GET,是一个真实存在的安全问题。现在你知道了。

拿不准用哪个的时候就这么判断:只是去问问、取点东西 → GET;要把东西交上去 → POST。

这节课我们只用 GET,因为它简单、看得见。等到第 23 课 MQTT、第 34 课联网天气站,你还会碰到它。

四、状态码:先看它,再看代码

服务器答话的时候,第一句不是内容,是一个三位数字,这个东西叫状态码。它是你排查时最值钱的一条线索。

状态码 意思 你该干什么
200 成功 你要的东西就在返回内容里
404 找不到 那边没有你请求的这个地址——多半是网址写错了
500 服务器自己出错了 不是你的事,等会儿再试
403 不让看 需要钥匙(API key),或者你的访问被拒了
429 你问得太频繁了 被限流了,等一会儿再试

这张表里,前三个你必须记住。 我要专门说一句 404500 的区别,因为这两个混起来会浪费你一整晚:

  • 404 是"你找错门了"——地址不对,问题在你这边(或者对方把东西挪走了)
  • 500 是"我家里出事了"——门找对了,是服务器自己倒了,跟你的代码一个字的关系都没有

记住这句话:看到不是 200,先看状态码,再怀疑自己的代码。 这就是第 5 课那句"先看现象,再猜原因"在联网里的样子——在硬件里,现象是灯不亮;在联网里,现象就是这个三位数。

五、返回内容不是网页,是一堆给程序看的文本

这一节要讲清一件事,它是很多人学了半年还没搞明白的一个坎。

你在浏览器里打开一个网页,看到的是排版好的标题、图片、按钮但你的板子拿到的,是完全不一样的东西。

浏览器拿到的 板子拿到的
内容 一堆文字(HTML) 一堆文字(大多是 JSON)
谁加工了 浏览器帮你"渲染"成了网页 没人加工,原样打印

关键在"渲染"这两个字。 服务器发给浏览器的,其实是一段描述"这个页面该长什么样"的文字,浏览器拿到之后照着这段文字把页面画出来,这段文字就叫 HTML。这就是上一课埋的那颗种子:板子写说明书,浏览器照着搭。

而板子去请求数据接口的时候,对方回的是更纯粹的东西——只有数据,没有任何"怎么画"的说明。 那个格式叫 JSON,你看一眼就懂了:

JSON
{
  "latitude": 39.9,
  "current": {
    "time": "2026-09-17T10:00",
    "temperature_2m": 24.3
  }
}

看明白了吗?就这么几条规矩:{} 是"一包东西","名字": 值 是一条(名字要用双引号括起来),[] 是"一串",{} 里面还能再套 {}。它就是一串有格式的文本,没有加密,没有玄机,你肉眼就能读懂。

那怎么把 24.3 抠出来? 第 7 课你学过"先打印,再判断"——这节课你只要把它整个打出来看就行。 真正要从中取值的时候(第 34 课联网天气站),我们会用一个叫 ArduinoJson 的库。现在不用急,先学会"看到它、认识它"。

六、动手:让板子取一段真实的数据回来

第一步,先把 WiFi 连上——这段不用新代码,第 20 课原样搬过来。连不上的话,回去翻第 20 课第五节的排查顺序。

第二步,发一个 GET 请求:

C++
#include <WiFi.h>
#include <HTTPClient.h>

const char* WIFI_NAME = "你家 WiFi 名字";
const char* WIFI_PASS = "你家 WiFi 密码";

void setup() {
  Serial.begin(115200);
  delay(1500);

  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_NAME, WIFI_PASS);
  Serial.print("正在连 WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("连上了,IP:");
  Serial.println(WiFi.localIP());
}

void loop() {
  HTTPClient http;

  String url = "http://api.open-meteo.com/v1/forecast"
               "?latitude=39.9&longitude=116.4&current=temperature_2m";

  Serial.println("请求地址:" + url);
  http.begin(url);

  int code = http.GET();          // 发出去,拿回一个状态码
  Serial.print("状态码:");
  Serial.println(code);

  if (code == 200) {
    String body = http.getString();   // 把返回的文本整个拿回来
    Serial.println("返回内容:");
    Serial.println(body);
  } else {
    Serial.println("没成功——先看状态码,再怀疑代码");
  }

  http.end();       // 用完要收尾,不然连接会越攒越多
  delay(10000);     // 别刷太快,免费接口有限制
}

烧进去,打开串口监视器。你会看到屏幕上滚出一大堆东西,长得跟上面那段 JSON 差不多。这就是从几百公里外的一台服务器上传回来的、此时此刻的真实数据。

关于那个网址,我说三件事。

① 它是公网上的一个免费天气接口,不需要注册、不需要 API key。

② 它随时可能挂。 免费接口就是这样——维护它的人不欠你什么,哪天关了就是关了。这不是你的代码错,第八节专门讲。

③ 如果你的库版本编译时报错,说 begin() 的参数不对,改成这两行的写法:

C++
WiFiClient client;
http.begin(client, url);

报错原文是最好的线索,把它复制给 AI,比描述现象有用得多。

第三步,故意制造一个 404——这一步别跳过,它比前面那步还值钱。 把网址里的 /v1/forecast 改成 /v1/forecats(故意拼错),再跑一遍,看状态码打印出什么。404。现在你亲眼见过它了——以后调试时再看到这个数,你不会慌,你知道那是"地址找错了",而不是"我的板子坏了"。

七、失败的时候,按这个顺序查

这一课的排查又跟前面两课不一样。 第 20 课查的是"能不能进网",第 21 课查的是"别人能不能连上我",这一课查的是"我出去这一趟,卡在哪一段"。

第 1 步:WiFi 连上了吗

先看串口有没有打印出 IP 地址。 没有 → 别查了,回第 20 课。 IP 都没拿到,后面全是白费劲。这一步看着废话,但它排在最前面是有道理的:很多人会跳过它,直接怀疑接口。

第 2 步:拿电脑浏览器访问同一个网址

这一步能省掉你一半的排查时间,我说真的。 把代码里那个 url 原封不动复制出来,粘到电脑浏览器的地址栏里回车,然后看:

电脑上打不开 电脑上能打开
问题不在你的板子(对方服务器挂了 / 你家网不通) 问题在板子这边
你的代码一个字都不用改 回第 1 步查板子,或者往下看状态码

这一步的意义在于:它把"外面的世界"和"你的代码"一刀切开了。不然你会陷入最痛苦的一种调试——改半天代码,其实是对方服务器倒了。

第 3 步:状态码是多少

回到那张表看一眼:404 → 地址错了,仔细对一遍网址,一个字符一个字符对;500对方的锅,等十分钟再试429 → 你请求太频繁了,delay 调大一点403 → 这个接口要 API key,换一个;负数(比如 -1根本没连上,回第 1 步查 WiFi。

第 4 步:把返回内容的前面一段打出来

有些接口失败的时候不是给你一个错误码,而是回一段说明文字。你不知道它说了什么,就只能瞎猜。 把返回内容整个打印出来,往往答案就在里面。

第 5 步:是不是这个接口需要 https

有些网站只支持 https://,你用 http:// 去请求它会直接失败。 这种情况下得换一套写法(WiFiClientSecure),比现在这个麻烦一些。判断方法:把网址改成 https:// 粘到浏览器里试试——如果 http 打不开、https 能打开,那就是这个问题。

我在第一节就说过:联网故障看不见摸不着。 但现在你手上有一套五步顺序了,每一步都在回答一个具体的问题:网通了吗?外面活着吗?对方说什么了?它回了啥?是不是协议不对?这比"我再改改代码试试"强一百倍。

八、必须提醒你的一件事:免费接口不欠你什么

这一段我要专门说,因为它是很多人放弃联网课的地方。

公网上的免费接口有这么几个特点,你提前知道了,就不会怀疑自己

  1. 随时可能挂。 今天好好的,明天就 500 了,后天可能域名都没了。
  2. 可能有限流。 一分钟请求超过多少次,它就把你拒了(429)。
  3. 可能变规矩。 昨天不用注册,今天要 key 了;昨天返回这个字段,今天改名了。
  4. 可能很慢。 有时候要等三五秒才回,不是你的板子卡了。

最要命的是——这四种情况,从你的板子上看,现象都差不多:请求失败了。 所以你一定要养成刚才第 2 步那个习惯:先拿电脑浏览器试一遍。电脑上也不行,那就真不是你的问题。 换个接口,或者过两天再试,都行。别对着正确的代码改一整晚。

说句实在的:你现在体会到的是真实开发者的日常。真实项目里,大部分时间不是花在"写代码",而是花在"搞清楚为什么这次又不行了"。写得快不算本事,查得准才算。

自测

单选题关于 GET 和 POST,下面哪个说法是对的?
单选题板子请求一个接口,状态码打印出来是 404。下面哪个判断是对的?
单选题板子请求接口一直失败。按这节课的思路,最省时间的第一步是什么?
问答题为什么板子拿到的返回内容,跟你在浏览器里看到的网页完全不一样?
拓展HTTPS 和 HTTP 差在哪?为什么板子访问 https 网站要额外折腾?

这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。

提示:搜"WiFiClientSecure ESP32 证书指纹"、"TLS 握手 是什么"。想一想:如果板子没法确认"对面真的是那台服务器",会发生什么?

拓展返回的那堆 JSON,怎么才能只把温度抠出来?

这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。

提示:搜"ArduinoJson 解析 示例"、"JSON 嵌套 取值"。想一想:如果不用库,靠自己在一大串文字里查找字符,会遇到什么麻烦?

本节你要动手做的事

  • [ ] 先连上 WiFi:把第 20 课的代码搬过来,确认串口打印出 IP
  • [ ] 发出第一个 GET 请求:跑通那段代码,看状态码是不是 200
  • [ ] 把返回内容整段读完不要只看开头就滑走,找到里面那个温度值
  • [ ] 故意制造 404:把网址路径拼错,看状态码变成几。记住这个数
  • [ ] 用电脑浏览器访问同一个网址:确认它活着,也看看电脑上"渲染"出来的样子,和板子拿到的文本差多少
  • [ ] 把返回内容前 100 个字符抄进笔记:以后接口变了,你能对比出来哪里变了
  • [ ] delay 从 10000 改成 1000 试试:看看多久之后会开始出问题

这一节课,你的板子第一次跟外面的世界发生了关系。

前面十九节课,它读的全是你桌上的东西:你房间的光、你手边的距离、你说话的声音。今天它读到的是几百公里外、此时此刻真实的天气。而你只写了不到三十行代码。

我觉得这件事值得你停下来想一想。但原理其实很朴素——报名字、拿地址、把请求送出去、把答案接回来。你把这几层都看穿了,你就不只是在"抄代码"。

下一节,我们上第 23 课:MQTT 与巴法云。今天你是主动去问——你问了才有答案。下一节我们要学一种"不用问,消息自己会来"的方式:手机发一条消息,板子那边立刻就动。

这才是"远程控制"真正的样子。