ESP32-Web-Server编程-建立第一个网页
ESP32-Web-Server编程-建立第一个网页
HTTP 简述
可能你每天都要刷几个短视频,打开几个网页来娱乐一番。当你打开一个网络上的视频或者图片时,其实际发生了下面的流程:
其中客户端就是你的浏览器啦,服务器就是远程一个存放视频或者图片的电脑啦。他们之间传输数据时需要一个约定的标准,就像两个设备约定共同用一种语言说话一样,目前使用较多的就是 HTTP协议啦。
本系列博客基于乐鑫最流行的开源 ESP-IDF 开发环境。ESP-IDF 中 HTTP Server 组件提供了在 ESP32 上运行轻量级 Web 服务器的功能。
HTTP 的基础的方法
http 1.0定义了3种方法:GET,POST,HEAD
http 1.1新增了6种方法:PUT,DELETE,Options,Trace,Connect,Patch
作为新手,我们主要理解两种方法 GET、POST 方法就可以了。
-
GET 方法:GET方法用于使用给定的URI从给定服务器中检索信息,即从指定资源中请求数据。使用GET方法的请求应该只是检索数据,不应对数据产生其他影响。相当与从服务器接收数据。
-
POST方法:用于将数据发送到服务器以创建或更新资源。POST请求永远不会被缓存,且对数据长度没有限制;我们无法从浏览器历史记录中查找到POST请求。目前,几乎所有的提交操作都是通过该方法完成。相当于向服务器发送数据。
HTTP 的 URL、URI
服务器上的文件资源很多,访问哪个资源?用 URI\URL 来指定要访问的资源。
URI = Universal Resource Identifier 统一资源标志符,用来标识抽象或物理资源的一个紧凑字符串。
URL = Universal Resource Locator 统一资源定位符,一种定位资源的主要访问机制的字符串,一个标准的URL必须包括:protocol、host、port、path、parameter、anchor。 一个典型的 URL 标识:
协议://主机[:端口]URI
举个栗子先大致理解下他们的含义就可以了,随着学习的深入大家会慢慢理解的更多的。
https://www.baidu.com:8080/iot-wang/readme.html?user=xmh&id=1#test
通过解析上述 URL 可以得到各部分的值如下所示。协议:https。也可以是 ftp、tftp
服务器主机域名:www.baidu.com
服务器端口号:8080
要查询的目标资源路径:/iot-wang/readme.html
客户端传递给服务器的附带参数:? 号开始后的内容,即 user=xmh&id=1,多个参数之间用 & 标识。
目标资源中可能有多个可以访问的资源,比如一个文章有多个段落,指定更详细的段落参数:# 号后的内容,即 test,也可以使用 & 连接多个锚点。
HTTP 的返回码
打开网页时显示 404?使用手机或者电脑的童鞋可能遇到过这种情况。
客户端发起一个请求后,服务器可以返回一个数字代表此次请求是否成功。数字 200 代表此次通信成功,其他数字代表此次通信有点问题:
(1)1xx(提示信息)
1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
(2)2xx(正确)
2xx 类状态码表示服务器成功处理了客户端的请求,常见的有:
「200 OK」是最常见的成功状态码,表示一切正常。如果是非 HEAD 请求,服务器返回的响应头都会有 body 数据。
「204 No Content」也是常见的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据。
(3)3xx(重定向)
3xx 类状态码表示客户端请求的资源发送了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。
「301 Moved Permanently」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。
「302 Moved Permanently」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。
「304 Not Modified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,用于缓存控制。
301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。
(4)4xx(客户端错误)
4xx 类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。
「400 Bad Request」表示客户端请求的报文有错误,但只是个笼统的错误。
「403 Forbidden」表示服务器禁止访问资源,并不是客户端的请求出错。
「404 Not Found」表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。
[408 Request Timeout]该响应状态码意味着服务器想要关闭这个未使用的连接。
(5)5xx(服务器错误)
5xx 类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。
「500 Internal Server Error」与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。
「501 Not Implemented」表示客户端请求的功能还不支持,类似“即将开业,敬请期待”的意思。
「502 Bad Gateway」通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。
「503 Service Unavailable」表示服务器当前很忙,暂时无法响应服务器,类似“网络服务正忙,请稍后重试”的意思。
ESP32 上如何实现网页的发送
前端代码
前端代码负责呈现网页上的特效、网页的布局、图片、视频等内容。网站前端工程师的工作内容就是将美工设计的效果图的设计成浏览器可以运行的网页,并和后端开发工程师配合做网页的数据显示和交互。
在本系列课程中前端代码主要是HTML+CSS+JAVASCRIPT。
注意,服务器只是提供前端代码的设计文本,客户端如何解释(即显示)由客户端决定。
后端代码
后端代码就是网站的逻辑部分,主要是数据的处理,以及如何响应客户端的请求。比如客户端发起一个不支持的请求,后端代码经过判断会返回一个错误码。
在本系列课程中前端代码主要是C语言代码,感兴趣的也可以了解下可能涉及的数据库。
需求及功能解析
本节演示如何在 ESP32 上使用 wifi,并使用一个 html 文件。
示例解析
目录结构
├── CMakeLists.txt
├── main
│ ├── CMakeLists.txt
│ └── main.c User application
├── components
│ └── fs_image└── index.html└── ...
| └── url_handlers└── url_handlers.c└── ...
└── README.md This is the file you are currently reading
-
目录结构主要包含主目录 main,以及组件目录 components.
-
其中组件目录components中包含了用于存储网页文件的 fs_image 目录(即前述前端文件),以及用于记录 ESP32 上接收来自服务器的请求,并作出响应的 url_handlers 目录(即后端文件)。如前所述,浏览器可以通过 URL 请求服务器端的资源(包括数据和文件),每个 URL 到来时都可以设计一个函数,来决定如何响应该 URL 请求,这便是 url_handlers 要完成的功能。
建立前后端代码
-
为了保存 html 文件以及图片文件到 ESP32 上,url_handlers 目录的 CMakeLists.txt 使用内嵌数据的方式将 fs_image目录的 index.html 和 favicon.ico 文件保存在 ESP32 中:(此外前端代码)
idf_component_register(SRCS "url_handlers.c"INCLUDE_DIRS "include"PRIV_REQUIRES esp_http_serverEMBED_FILES "../fs_image/favicon.ico" "../fs_image/index.html")
-
为了在打开网页时显示 index.html 中的内容,在 url_handlers.c 中实现了 一个处理函数
index_html_get_handler()
。这部分是后端代码。/* Handler to redirect incoming GET request for /index.html to /* This can be overridden by uploading file with same name */ static esp_err_t index_html_get_handler(httpd_req_t *req) {extern const char html_start[] asm("_binary_index_html_start");extern const char html_end[] asm("_binary_index_html_end");const size_t html_size = (html_end - html_start);httpd_resp_set_type(req, "text/html");/* Add file upload form and script which on execution sends a POST request to /upload */httpd_resp_send_chunk(req, (const char*) html_start, html_size);/* Respond with an empty chunk to signal HTTP response completion */return httpd_resp_send_chunk(req, NULL, 0); }
-
在实现了 html 文件以及 对应的 handles 后,可以在 main.c 中注册对应的 handler:
static httpd_handle_t start_webserver(void) {httpd_handle_t server = NULL;httpd_config_t config = HTTPD_DEFAULT_CONFIG();config.lru_purge_enable = true;// Start the httpd serverESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);if (httpd_start(&server, &config) == ESP_OK) {// Set URI handlersESP_LOGI(TAG, "Registering URI handlers");for (int i = 0; i < sizeof(httpd_uri_array) / sizeof(httpd_uri_t); i++) {if (httpd_register_uri_handler(server, &httpd_uri_array[i]) != ESP_OK) {ESP_LOGE(TAG, "httpd register uri_array[%d] fail", i);}}ESP_LOGI(TAG, "Success starting server!");return server;}ESP_LOGI(TAG, "Error starting server!");return NULL; }
如此,当打开网页时,浏览器会自动请求名为 index.html 的文件,并显示其中的内容。
编译并烧录固件到设备中
1)在工程目录,打开配置菜单
idf.py menuconfig
主要是配置 wifi 连接的名称和密码:
2)编译烧录固件到设备中
idf.py -p PORT build flash monitor
(Replace PORT with the name of the serial port to use.)
(To exit the serial monitor, type Ctrl-]
.)
如果你是新手,请参考 Getting Started Guide 搭建编译环境。
3)网页显示
设备烧录固件后,启动该设备,从 log 中查看设备的 IP地址:
I (3288) app_wifi: got ip:192.168.47.100
I (3288) esp_netif_handlers: sta ip: 192.168.47.100, mask: 255.255.255.0, gw: 192.168.47.1
I (3288) example_main: Starting server on port: '80'
I (3298) example_main: Registering URI handlers
I (3298) example_main: Success starting server!
这里假设设备 IP 地址是 192.168.47.100.
让手机或者电脑与 ESP32 连接同一个路由器,然后打开手机或者电脑上电浏览器,输入上述IP地址,即可打开网页:
上述示例网页即是本例程 fs_images 目录的 index.html 文件在该浏览器中所程序的样子。
4)功能演示
本节主要是呈现一个网页给用户。
讨论
1)输入网址后,浏览器会自动请求 favicon.ico(即上述网页中第一行显示的图标)。
默认情况下,当请求一个网站的 “/” 目录内容时,会默认打开该目录的 index.html 文件。
同样的,默认情况下,浏览器会自动请求 "/"目录下的 favicon.ico 文件,用作网址栏的一个标识图像。
2)如何设计 index.html 文件中的内容,使之在网页上呈现合适的内容?
这正是本系列博客主要介绍的内容。以试验促进理解,在测试实践中学习,敬请参考后续章节。
总结
1)本节主要是介绍 HTTP 协议、Web 编程的基础知识,包括HTTP 的基础的方法;什么是 URL、URI;HTTP 的返回码;
2)本节还介绍了 ESP32 上 HTTP 编程的要点,包括如何建立前端、后端代码,它们如何相互作用以实现一个 Web 应用。
资源链接
1)ESP32-Web-Server ESP-IDF系列博客介绍
2)对应示例的 code 链接 (点击直达代码仓库)
3)下一篇:ESP32-Web-Server编程-HTML 基础
(码字不易感谢点赞或收藏)
相关文章:

ESP32-Web-Server编程-建立第一个网页
ESP32-Web-Server编程-建立第一个网页 HTTP 简述 可能你每天都要刷几个短视频,打开几个网页来娱乐一番。当你打开一个网络上的视频或者图片时,其实际发生了下面的流程: 其中客户端就是你的浏览器啦,服务器就是远程一个存放视频或…...

csgo/steam游戏搬砖项目的五大认知误区
CSGO/steam游戏搬砖项目的5大认知误区 1、卡价越高越难选品?越没利润? 2、明明buff卖价《 steam求购价,为什么还能赚钱? 3、实名资料少就没法批量操作账号? 4、本金少就没法玩? 5、这个项目的风险是不是很大…...
ASCII sorting
描述 输入一个字符串,对其字符进行排序,输出其字符按ASCII码升序排列。 输入 无空格字符串 输出 按ASCII码升序输出其字符。 样例输入 and 样例输出 adn code(c版本) #include<stdio.h> #include<stdlib.h> // qs…...

redis--高可用之持久化
redis高可用相关知识 在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。 但是在Redis语境中,高可用的含义似乎要宽泛一些,除了保证提供正常服务( 如主…...

『VUE3 の 要点摘录』
✅v-model 用法 v-model 原生方法: v-model computed : 更改名字: 多个 v-model 绑定 处理 v-model 修饰符 ✅TS项目报错 1、TypeScript 错误 “Module ‘…index’ has no default export” // tsconfig.json {...."compilerOpt…...

Buzz库python代码示例
Buzz库来编写一个下载器程序。 php <?php require_once vendor/autoload.php; // 引入Buzz库 use Buzz\Browser; use Buzz\Message\Response; $browser new Browser(); // 设置 $browser->setHttpClient(new HttpClientProxy([ host > , port > , ])…...

Django路由分发
首先明白一点,Django的每一个应用下都可以有自己的templates文件夹,urls.py文件夹,static文件夹,基于这个特点,Django能够很好的做到分组开发(每个人只写自己的app),作为老大&#x…...

【UGUI】中Content Size Fitter)组件-使 UI 元素适应其内容的大小
官方文档:使 UI 元素适应其内容的大小 - Unity 手册 必备组件:Content Size Fitter 通常,在使用矩形变换定位 UI 元素时,应手动指定其位置和大小(可选择性地包括使用父矩形变换进行拉伸的行为)。 但是&a…...

第二十章Java博客
如果一次只完成一件事情,很容易实现。但现实生活中,很多事情都是同时进行的。Java中为了模拟这种状态,引入了线程机制。简单地说,当程序同时完成多件事情时,就是所谓的多线程。多线程应用相当广泛,使用多线…...

实验一 SAS 基本操作和数据表的导入 2023-11-29
一、上机目的 熟悉SAS的集成环境并掌握它的基本操作。理解SAS程序的结构,理解其中的过程,过程选项,语句,语句选项等概念,掌握SAS编程技术。 二、上机内容 主要有SAS操作界面、SAS窗口操作、SAS菜单操作、SAS按钮操作…...

YOLOv5改进之ShuffleNetV2
目录 一、原理 网络结构 二、代码 三、应用到YOLOv5 一、原理...

tcp/ip协议 error=10022 Winsock.reg Winsock2.reg
tcp/ip协议 error10022 这2个注册表选项千万不能删除,否则上不了网。 按下windows键R键,输入regedit,打开注册表,在文件目录里找到如下两个文件夹,删除这两个文件夹。 路径:HKEY_LOCAL_MACHINE\System\C…...

【Redis基础】Redis基本的全局命令
✅作者简介:大家好,我是小杨 📃个人主页:「小杨」的csdn博客 🐳希望大家多多支持🥰一起进步呀! Redis基本的全局命令 1,KEYS命令 语法:KEYS pattern KEYS命令用来查询服…...

Vite 了解
1、vite 与 create-vite 的区别 2、vite 解决的部分问题 3、vite配置文件的细节 3.1、vite语法提示配置 3.2、环境的处理 3.3、环境变量 上图补充 使用 3.4、vite 识别,vue文件的原理 简单概括就是,我们在运行 npm润dev 的时候,vite 会搭起…...
oracle常用通用sql脚本——查询前用户的表空间信息
oracle常用通用sql脚本——查询前用户的表空间信息 一、查询前用户的表空间信息1、 查询当前用户的所有表空间2、 已G为单位3、 已MB为单位 二、以上俩段sql查出结果集存在差异的原因 一、查询前用户的表空间信息 1、 查询当前用户的所有表空间 SELECT * FROM dba_tablespace…...

Python内置类属性`__name__`属性的使用教程
更多Python学习内容:ipengtao.com Python中的__name__是一种内置的特殊属性,通常用于判断模块是作为主程序运行还是作为模块被导入。本文将深入讲解__name__属性的用法,通过丰富的示例代码展示其在不同情景下的应用。 模块作为主程序运行 当一…...

BUUCTF-pwn-ciscn_2019_ne_51
简单查看保护: 32为程序没有canary没有PIE,应该是简单的栈溢出。我们照着这个思路去找溢出点在哪,运行下程序看看什么情况: 程序上来是输入一个密码验证。随便输入下错误直接退出。因此我们需要到IDA中看看怎么回事: 主…...
【限时免费】20天拿下华为OD笔试之【哈希表】2023Q2B-选修课【欧弟算法】全网注释最详细分类最全的华为OD真题题解
文章目录 题目描述与示例题目描述输入输出示例一输入输出说明 示例二输入输出说明 解题思路代码PythonJavaC时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目描述与示例 题目描述 现有两门选修课,每门选修课都有一部分学生选修,每个学生都有…...

Android关于杀掉进程的方案
《风波莫听穿林打叶声》—— 苏轼 〔宋代〕 三月七日,沙湖道中遇雨,雨具先去,同行皆狼狈,余独不觉。已而遂晴,故作此词。 莫听穿林打叶声,何妨吟啸且徐行。 竹杖芒鞋轻胜马,谁怕?一蓑…...
mysql数据库基本概念简介
概述 为什么要使用数据库? 答:实现数据的持久化。 数据库存储类型多样,存储量大。由于其他文件等介质。 概念 DB:database(数据库),保存数据的仓库,本质是一个文件系统。 DBMS:数据库管理系统,常说的Mysql数…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...