想用 LuatOS Air780EPM 开发板实现 HTTP 数据传输?本文从底层原理出发,逐步引导你完成 HTTP 客户端的搭建,并通过真实案例展示完整的开发流程。
一、HTTP 概述
1.1 什么是 HTTP?
HTTP 全称为 HyperText Transfer Protocol,中文即“超文本传输协议”。它是一种应用层协议,采用标准的请求-响应模型,通常运行在 TCP 之上,规定了客户端可以向服务器发送何种消息以及预期得到何种响应,常用于分布式、协作式和超媒体信息系统。
1.2 什么是 HTTPS?
HTTPS 全称为 HyperText Transfer Protocol Secure,中文即“超文本传输安全协议”。它并非一种新的协议,而是在 HTTP 之下插入了一层 SSL/TLS 安全通道,同样运行在 TCP 之上。通过加密与身份认证,HTTPS 确保客户端与服务器之间交换的消息不被窃听或篡改,从而为分布式、协作式和超媒体信息系统提供了保密性、完整性与身份可验证的通信基础。
1.3 HTTP 的工作原理(请求-响应模型)
HTTP 采用请求-响应模型:客户端(如浏览器)向服务器发送请求,服务器以状态码和对应资源的表示(如 HTML 字节流)作出响应。
1.3.1 HTTP 请求报文
一个完整的 HTTP 请求包含请求行、请求头、空行、请求体四部分:
1. Request line(请求行)
Method:请求方式,如 GET、POST。
Request-URL:需要访问的目标路径,比如 /index.html。
HTTP-Version:HTTP 协议版本号,比如 HTTP/1.1。
2. Header Lines(请求头)
由键值对组成,每行一对。请求头包含关于客户端环境和请求正文的重要信息。常见的请求头有:
Host:指定请求的服务器的域名和端口号(HTTP/1.1 必需字段)。
User-Agent:包含发起请求的应用程序信息(浏览器类型、操作系统等)。
Accept:告知服务器客户端能够处理哪些类型的媒体资源(如 text/html, application/json)。
Content-Type:(用于有 Body 的请求)请求体的媒体类型(如 application/json, application/x-www-form-urlencoded)。
Content-Length:(用于有 Body 的请求)请求体的长度(字节)。
3. Blank line(空行)
就是一个空行,用来分隔头部和正文,告诉服务器:“头部结束,下面是正文了”。
4. Entity Body(请求体)
可选部分,主要用于 POST、PUT 等需要向服务器发送数据的请求。
内容格式由 Content-Type 头指定。
常见内容:表单数据(user=admin&pass=123)、JSON 字符串({"user":"admin"})、文件数据等。
请求报文示例如下:
1.3.2 HTTP 响应报文
一个完整的 HTTP 响应报文与请求报文几乎一一对应,也是四部分:
1. Status Line(状态行)
HTTP-Version:与请求消息中的版本相匹配,如 HTTP/1.1。
Status Code:三位数字,标识请求的处理结果,如 200、404。
Reason-Phrase:状态码的简短文字描述,如 OK、Not Found。
2. Header Lines(响应头)
一样每行是一个“键值对”,响应头包含关于响应的附加信息。常见的响应头有:
Server:包含处理请求的服务器软件信息。
Date:响应生成的日期和时间。
Content-Type:响应体的媒体类型(如 text/html; charset=UTF-8)。
Content-Length:响应体的长度(字节)。
Content-Encoding:响应体使用的编码(如 gzip),用于压缩。
Cache-Control:指示响应内容应如何被缓存。
3. Blank Line(空行)
响应头和响应体之间的分隔符,表示响应头的结束。
4. Response Body(响应体)
可选部分,包含服务器返回的实际资源内容。
内容格式由 Content-Type 头指定。
常见内容:HTML 文档、JSON 数据、图片、CSS、JavaScript 文件等。
响应报文示例如下:
1.4 HTTP 请求方法
HTTP 客户端发出请求,告知服务端需要执行不同类型的请求命令,这些命令被称为 HTTP 方法。
1.4.1 常见 HTTP 请求方法
下表展示的是常见的 HTTP 请求方法:
1.4.2 各版本定义的 HTTP 请求方法
HTTP 标准目前有 HTTP/1.0、HTTP/1.1、HTTP/2 、 HTTP/3 四个版本,介绍如下:
HTTP/1.0
HTTP/1.0 定义了以下三种请求方法:
GET:请求指定的资源。
POST:提交数据以处理请求。
HEAD:请求资源的响应头信息。
HTTP/1.1
HTTP/1.1 引入了更多的请求方法:
GET:请求指定的资源。
POST:提交数据以处理请求。
HEAD:请求资源的响应头信息。
PUT:上传文件或者更新资源。
DELETE:删除指定的资源。
OPTIONS:请求获取服务器支持的请求方法。
TRACE:回显服务器收到的请求,主要用于诊断。
CONNECT:建立一个隧道用于代理服务器的通信,通常用于 HTTPS。
HTTP/2
HTTP/2 基本上沿用了 HTTP/1.1 的方法,但对协议进行了优化,提高了传输效率和速度。HTTP/2 也引入了新的特性,如多路复用、头部压缩和服务器推送等。
HTTP/3
HTTP/3 基于 QUIC 协议实现,继续使用 HTTP/2 的方法。HTTP/3 主要改进了传输层,使用 UDP 代替 TCP 以提高传输速度和可靠性。
1.5 HTTP 状态码
HTTP 状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,响应分为五类:
二、http 与 httpplus 库的介绍
注意: LuatOS 仅支持 HTTP/1.0 和 HTTP/1.1。
HTTP 在如下的场景,开发成本是最低的:
-
终端和云端交换文件,不用开发复杂的分包组包协议;
-
终端从云端下载各种参数,或者终端向云端提交各种参数, 不用设计报文协议,用 http 的参数即可,非常方便。
LuatOS 提供了 http 核心库 和 httpplus 扩展库 实现了 http 客户端。
http 核心库 和 httpplus 扩展库 的区别如下:
三、演示功能概述
在使用示例代码测试时,如果遇到测试域名请求不成功的情况,可以向工作人员进行反馈。
1、http_app:使用 http 核心库,演示以下几种应用场景的使用方式
普通的 http get 请求功能演示;
http get 下载压缩数据的功能演示;
http get 下载数据保存到文件中的功能演示;
http post 提交表单数据功能演示;
http post 提交 json 数据功能演示;
http post 提交纯文本数据功能演示;
http post 提交 xml 数据功能演示;
http post 提交原始二进制数据功能演示;
http post 文件上传功能演示;
2、httpplus_app:使用 httpplus 扩展库,演示以下几种应用场景的使用方式
普通的 http get 请求功能演示;
http get 下载压缩数据的功能演示;
http post 提交表单数据功能演示;
http post 提交 json 数据功能演示;
http post 提交纯文本数据功能演示;
http post 提交 xml 数据功能演示;
http post 提交原始二进制数据功能演示;
http post 文件上传功能演示;
3、netdrv_device:配置连接外网使用的网卡,目前支持以下三种选择(三选一)
(1) netdrv_4g:4G 网卡
(2) netdrv_eth_spi:通过 SPI 外挂 CH390H 芯片的以太网卡
(3) netdrv_multiple:支持以上两种网卡,可以配置两种网卡的优先级
四、演示硬件环境
1、Air780EPM V1.3 版本开发板一块 + 可上网的 sim 卡一张 +4g 天线一根 + 网线一根:
sim 卡插入开发板的 sim 卡槽
天线装到开发板上
网线一端插入开发板网口,另外一端连接可以上外网的路由器网口
2、TYPE-C USB 数据线一根 + USB 转串口数据线一根,Air780EPM V1.3 版本开发板和数据线的硬件接线方式为:
Air780EPM V1.3 版本开发板通过 TYPE-C USB 口供电;(外部供电/USB 供电 拨动开关 拨到 USB 供电一端)
TYPE-C USB 数据线直接插到核心板的 TYPE-C USB 座子,另外一端连接电脑 USB 口;
五、演示软件环境
5.1 软件环境
-
烧录工具:Luatools 下载调试工具
-
内核固件:Air780EPM V2012 版本固件(理论上,2025 年 8 月 10 日之后发布的固件都可以)
-
脚本文件:Air780EPM HTTP 脚本文件
-
LuatOS 运行所需要的 lib 文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件。
准备好软件环境之后,接下来查看 Air780EPM 产品手册中“Air780EPM 开发板使用手册 -> 使用说明”,将本篇文章中演示使用的项目文件烧录到 Air780EPM 开发板中。
5.2 API 介绍
sys 库:https://docs.openluat.com/osapi/core/sys/
http 库:https://docs.openluat.com/osapi/core/http/
httpplu 库:https://docs.openluat.com/osapi/ext/httpplus/
六、程序结构
6.1 文件说明
main.lua:主程序入口文件,负责初始化系统、启动网络驱动和 HTTP 演示任务。
netdrv_device.lua:网络设备配置文件。
http_app.lua:http 核心库的演示文件,包含 13 个示例场景。
httpplus_app.lua:httpplus 扩展库的演示文件,包含 9 个示例场景。
logo.jpg:供上传、下载测试使用的素材文件。
netdrv/:网络驱动相关文件。
netdrv_4g.lua:4G 网络驱动。
netdrv_eth_spi.lua:SPI 以太网驱动。
netdrv_multiple.lua:多网络驱动管理。
七、核心模块详解
7.1 主程序 (main.lua)
主程序文件 main.lua 是整个项目的入口点。它负责初始化系统环境。
7.1.1 初始化流程
1. 项目和版本定义:
定义 PROJECT 和 VERSION 变量。
2. 日志记录:
使用 log.info``("main", PROJECT, VERSION) 在日志中打印项目名和版本号。
3. 看门狗初始化(如果支持):
配置并启动硬件看门狗,防止程序死循环卡死。
4. 加载功能模块:
加载网络驱动设备模块(netdrv_device)。
加载 HTTP 核心库示例模块(http_app.lua)。
加载 HTTPPLUS 扩展库示例模块(httpplus_app.lua)。
5. 启动任务调度器:
调用 sys.run() 启动 LuatOS 的任务调度器,开始执行各个任务。
7.2 网络驱动 (netdrv/)
网络驱动模块负责初始化和管理不同的网络连接方式,如 4G 和以太网。
7.2.1 4G 网络驱动 (netdrv_4g.lua)
监听 IP_READY 和 IP_LOSE 消息,监控网络连接状态。
设置默认网卡为 socket.LWIP_GP。
7.2.2 以太网网络驱动(netdrv_eth_spi.lua)
通过 SPI 接口外挂 CH390H 芯片实现以太网。
通过控制 GPIO20 引脚使能芯片供电。
配置 SPI0 接口参数,用于与 CH390H 芯片通信。
通过 netdrv.setup 函数配置以太网卡,并开启 DHCP 动态获取 IP 地址。
设置默认网卡为 socket.LWIP_ETH。
7.2.3 多网络驱动管理 (netdrv_multiple.lua)
管理多个网络驱动实例,根据配置选择合适的网络连接方式。
通过 exnetif.set_priority_order 函数配置多网卡的控制参数以及优先级。
通过 exnetif.notify_status 函数设置网卡状态变化通知回调函数。
7.3 HTTP 库演示模块(http_app.lua)
http_app.lua 是 LuatOS 中基于 http 核心库 所开发的 HTTP 应用功能模块。该模块通过调用 http.request 接口演示了 13 种 HTTP 请求场景,这 13 种演示功能如下。
7.3.1 下载回调函数
该函数在下载数据过程中被调用,用于实时监控下载进度。参数包括:
content_len:数据总长度。
body_len:已下载的数据长度。
userdata:用户自定义参数。
7.3.2 HTTP GET 请求功能
1. 普通 GET 请求
http_app_get() 函数演示了三种不同的 GET 请求场景:
-
基本的 HTTPS GET 请求。
-
设置超时时间和回调函数的 HTTPS GET 请求。
-
设置短超时和回调函数的 HTTP GET 请求。
2. 下载压缩数据
http_app_get_gzip() 函数演示了如何处理压缩格式的 HTTP 响应:
发送 GET 请求获取压缩的天气数据。
对响应内容进行解压缩处理。
解析解压后的 JSON 数据并提取信息。
3. 下载数据到文件
http_app_get_file() 函数演示了如何将 HTTP 响应直接保存到文件:
创建下载目录。
发送 GET 请求并设置 dst 参数指定保存路径。
验证下载文件的完整性。
按需删除临时文件。
7.3.3 HTTP POST 请求功能
1. 提交表单数据
http_app_post_form() 函数演示了如何发送表单格式的 POST 请求:
构造表单数据并进行 URL 编码。
设置正确的 Content-Type(application/x-www-form-urlencoded)。
发送请求并处理响应。
2. 提交 JSON 数据
http_app_post_json() 函数演示了如何发送 JSON 格式的 POST 请求:
使用 json.encode() 将 Lua 表转换为 JSON 字符串。
设置正确的 Content-Type(application/json)。
发送请求并处理响应。
3. 提交纯文本数据
http_app_post_text() 函数演示了如何发送纯文本数据格式的 POST 请求:
设置正确的 Content-Type(text/plain)。
发送请求并处理响应。
4. 提交 XML 数据
http_app_post_xml() 函数演示了如何发送 XML 格式的 POST 请求:
使用 Lua 的长字符串语法 [=[...]=] 定义 XML 内容。
设置正确的 Content-Type(text/xml)。
发送请求并处理响应。
5. 提交原始二进制数据
http_app_post_binary() 函数演示了如何发送原始二进制格式的 POST 情况:
使用 io.readFile 读取 JPG 图片文件。
设置正确的 Content-Type(application/octet-stream)。
发送请求并处理响应。
上传成功后,可以通过指定网址查看上传的图片。
7.3.4 文件上传功能
http_app_post_file() 函数演示了如何通过 HTTP 上传文件:
调用辅助函数 post_multipart_form_data() 构造 multipart/form-data 格式请求。
支持单文件、多文件、单文本或多文本上传。
支持文本字段和文件字段混合上传。
7.3.5 任务管理机制
1. 主任务函数
该函数是模块的核心控制逻辑,实现了:
网络连接等待机制:通过循环检测 socket.adapter(socket.dft()) 和 sys.waitUntil("IP_READY", 1000) 等待网络就绪。
功能调用序列:按顺序调用所有 HTTP 功能演示函数。
循环执行策略:每次功能演示完成后等待 60 秒,然后再次开始循环。
2. 任务启动
通过 sys.taskInit 函数创建并启动一个新的任务来运行 httpplus_app_task_func 函数,使整个模块的功能在后台持续运行。
7.4 HTTPPLUS 库演示模块(httpplus_app.lua)
httpplus_app.lua 是 LuatOS 中基于 httpplus 扩展库所开发的 HTTP 应用功能模块。该模块通过调用 httpplus.request 接口演示了 9 种 HTTP 请求场景,这 9 种演示功能如下。
7.4.1 HTTP GET 请求功能
1. 普通 GET 请求
httpplus_app_get() 函数演示了两种不同的 GET 请求场景:
-
基本的 HTTPS GET 请求。
-
设置超时时间的 HTTP GET 请求。
2. 下载压缩数据
httpplus_app_get_gzip() 函数演示了如何处理压缩格式的 HTTP 响应:
发送 GET 请求获取压缩的天气数据。
对响应内容进行解压缩处理。
解析解压后的 JSON 数据并提取信息。
7.4.2 HTTP POST 请求功能
1. 提交表单数据
httpplus_app_post_form() 函数演示了如何发送表单格式的 POST 请求:
构造表单数据并进行 URL 编码。
存在 forms 参数并且不存在 files 参数,系统自动强制以 application/x-www-form-urlencoded 形式上传数据。
发送请求并处理响应。
2. 提交 JSON 数据
httpplus_app_post_json() 函数演示了如何发送 JSON 格式的 POST 请求:
使用 json.encode() 将 Lua 表转换为 JSON 字符串。
设置正确的 Content-Type(application/json)。
发送请求并处理响应。
3. 提交纯文本数据
httpplus_app_post_text() 函数演示了如何发送纯文本数据格式的 POST 请求:
设置正确的 Content-Type(text/plain)。
发送请求并处理响应。
4. 提交 XML 数据
httpplus_app_post_xml() 函数演示了如何发送 XML 格式的 POST 请求:
使用 Lua 的长字符串语法 [=[...]=] 定义 XML 内容。
设置正确的 Content-Type(text/xml)。
发送请求并处理响应。
5. 提交原始二进制数据
http_app_post_binary() 函数演示了如何发送原始二进制格式的 POST 情况:
使用 io.readFile 读取 JPG 图片文件。
设置正确的 Content-Type(application/octet-stream)。
发送请求并处理响应。
上传成功后,可以通过指定网址查看上传的图片。
7.4.3 文件上传功能
http_app_post_file() 函数演示了如何通过 HTTP 上传文件:
使用 files 参数上传文件。
系统会自动将请求设置为 POST 方法,并以 multipart/form-data 格式发送数据。
支持单文件、多文件、单文本或多文本上传。
支持文本字段和文件字段混合上传。
7.4.4 任务管理机制
1. 主任务函数
该函数是模块的核心控制逻辑,实现了:
网络连接等待机制:通过循环检测 socket.adapter(socket.dft()) 和 sys.waitUntil("IP_READY", 1000) 等待网络就绪。
功能调用序列:按顺序调用所有 HTTP 功能演示函数。
循环执行策略:每次功能演示完成后等待 60 秒,然后再次开始循环。
2. 任务启动
通过 sys.taskInit 函数创建并启动一个新的任务来运行 httpplus_app_task_func 函数,使整个模块的功能在后台持续运行。
八、演示功能
8.1 不同网卡切换
Air780EXX 模组支持单 4g 网卡,单 spi 以太网卡,多网卡。
切换网卡为 4G 网卡:
在 netdrv_device.lua 模块里只打开 netdrv_4g 模块。netdrv_4g.lua 模块中的代码不需要修改。
Luatools 工具日志打印:
如下图所示,如出现类似 I/user.netdrv_4g.ip_ready_func IP_READY 10.73.217.4 255.255.255.255 0.0.0.0 nil 的日志,则表示 4g 网卡连接成功。
切换网卡为以太网卡:
注意:Air780EPM 的以太网卡是通过 SPI 外挂 CH390H 芯片实现的。
在 netdrv_device.lua 模块里只打开 netdrv_eth_spi 模块。如果是使用开发板,netdrv_eth_spi 模块中的代码不需要修改。
Luatools 工具日志打印:
如出现类似 I/user.netdrv_eth_spi.ip_ready_func IP_READY 192.168.71.66 255.255.255.0 192.168.71.1 nil 的日志,则表示以太网卡联网成功。
多网卡自动切换:
如果需要多网卡,打开 require "netdrv_multiple",其余注释掉; 可根据自己的需求调整网卡的优先级,以下示例设置为以太网卡是最高优先级。
首先在 netdrv_device.lua 文件中只打开 netdrv_multiple 模块。
默认以太网卡进行连接
拔掉网线后,网络切换为 4g 网卡
8.2 HTTP 请求结果
前面介绍了 HTTP 核心库演示模块中演示了 13 种场景的 HTTP 请求,HTTPPLUS 扩展库演示模块中演示了 9 种 HTTP 请求。因此我们烧录程序成功后,在日志中搜索 success 200 ,程序默认每隔 1 分钟测试一轮,如果每轮出现 22 次 success 200,如以下日志所示,就表示成功,如果不够 22 次,则说明部分域名没有请求成功,此时可以通过详细日志所表示的含义,结合代码自行分析。
九、总结
至此,我们演示了使用不同网卡在 22 种场景下进行 HTTP 请求的全过程,相信聪明的你已经完全领悟 HTTP 请求的逻辑了,快来实际操作一下吧!