发帖
0 0 0

从零理解 HTTP · TCP · TLS:用 WB2 芯片访问心知天气

XEMOWO
中级会员

4

主题

2

回帖

262

积分

中级会员

积分
262
小安AI 31 0 昨天 17:05

🔓 从零理解 HTTP · TCP · TLS:用 WB2 芯片访问心知天气

一块 Ai-WB2 开发板 · 一行 HTTPS GET 请求 · 拆开看 TCP 怎么握手、TLS 怎么加密、HTTP 怎么传数据

HTTP TCP TLS mbedTLS 心知天气 API Ai-WB2


📖 一、HTTP 是什么

当你打开浏览器输入 https://api.seniverse.com/v3/weather/now.json,浏览器干了什么?

其实就一句话:按约定格式写了一封信,通过 TCP 管道寄出去,然后等回信。

"GET /v3/weather/now.json?key=xxx&location=shenzhen HTTP/1.1\r\n"
"Host: api.seniverse.com\r\n"
"User-Agent: Ai-WB2 XEMOWO\r\n"
"Accept: application/json\r\n"
"Connection: close\r\n"
"\r\n"

这就是 HTTP 的全部——一套纯文本的格式约定

HTTP 请求的结构

GET /v3/weather/now.json HTTP/1.1    ← 请求行:方法 + 路径 + 版本
Host: api.seniverse.com               ← 请求头:告诉服务器你是谁
User-Agent: Ai-WB2 XEMOWO             ←
Accept: application/json              ←
Connection: close                     ←
                                      ← 空行!表示头结束,开始消息体

HTTP 响应的结构

HTTP/1.1 200 OK                       ← 状态行:协议 + 状态码
Server: nginx                         ← 响应头:服务器信息
Content-Type: application/json        ←
                                      ← 空行!
{"results":[{...}]}                   ← 响应体:实际数据(JSON)

就这么简单。HTTP 不是魔法,它就是一段带格式的字符串。


🧱 二、HTTP 跑在哪?——TCP

HTTP 只是一段文本。文本怎么传到服务器?靠 TCP

┌──────────────────────────────┐
│ HTTP: "GET /weather HTTP/1.1"│  ← 应用层:定义"发什么"
├──────────────────────────────┤
│ TCP: 分段、编号、确认、重传    │  ← 传输层:定义"怎么传"
├──────────────────────────────┤
│ IP: 寻址、路由                │  ← 网络层:定义"往哪传"
├──────────────────────────────┤
│ WiFi: 无线电信号              │  ← 物理层
└──────────────────────────────┘

TCP 做了三件事:

  1. 分段:把 HTTP 报文切成一帧一帧的小包,每帧最多 1460 字节
  2. 保证到达:每个包都有编号。丢了就重发,乱序就排序,重复就去重
  3. 流量控制:服务器太慢就慢点发,太快就快发
sequenceDiagram participant A as 🔵 WB2 开发板 participant B as 📡 服务器 Note over A,B: TCP 三次握手 A->>B: SYN, seq=1000 B->>A: SYN+ACK, seq=5000, ack=1001 A->>B: ACK, ack=5001 Note over A,B: TCP 连接建立,开始传 HTTP A->>B: PSH, seq=1001, data="GET /weather HTTP/1.1..." B->>A: ACK, ack=1245 B->>A: PSH, seq=5001, data="HTTP/1.1 200 OK..." A->>B: ACK, ack=5672 Note over A,B: TCP 四次挥手关闭

关键区别:TCP 是管道,HTTP 是管道里流的水。
TCP 不关心你传的是 HTTP、MQTT 还是视频流——它只负责把字节完整送到。


🔐 三、HTTPS 多了什么?——TLS

HTTP 是明文。任何人抓包都能看到你发了什么。

HTTPS = HTTP + TLS。TLS 在 TCP 和 HTTP 之间加了一层加密:

HTTP                                HTTPS
──────                              ──────────
应用层  │ GET /weather               │ GET /weather
       │                            │
TLS 层 │ (无)                      │ 加密握手、证书验证、对称加密
       │                            │
传输层  │ TCP                        │ TCP

TLS 握手做了三件事:

  1. 证书验证:服务器出示证书,客户端验证"你是不是 api.seniverse.com"
  2. 密钥协商:双方协商出一个临时的对称密钥
  3. 加密通信:之后所有 HTTP 报文都用这个密钥加密

你的 WB2 日志里这行就是握手结果:

TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256
 │   │      │       │        │
 │   │      │       │        └─ 哈希算法:SHA-256
 │   │      │       └─ 加密算法:AES-128-GCM
 │   │      └─ 身份验证:RSA 签名
 │   └─ 密钥交换:ECDHE(椭圆曲线,前向安全)
 └─ 传输方式:TLS 1.2+

🔬 四、实战:一步一步拆解请求过程

用 WB2 的串口输出,你能看到每一层的真实耗时。

硬件

  • 🔵 Ai-WB2 开发板 × 1 (BL602 RISC-V)
  • 🔌 USB Type-C 数据线
  • 📶 可上网的 Wi-Fi

代码流程

sequenceDiagram participant A as 🔵 WB2 participant B as 📡 api.seniverse.com Note over A: 开始计时 t0 A->>B: 🔗 DNS 解析 + TCP 三次握手 Note over A: t1 - t0 = Connect time A->>B: 🔐 TLS 握手(证书+密钥协商) Note over A: t3 - t2 = Handshake time A->>B: 📤 HTTP GET 请求 Note over A: t3 → 开始等 B->>A: 📥 HTTP 200 + JSON 数据 Note over A: t4 - t3 = Server latency Note over A: t4 - t0 = Total RTT

核心代码

#define WEATHER_API_KEY  "SY6RZjFvE-3_ogTp_"
#define WEATHER_LOCATION "shenzhen"

#define WEB_SERVER "api.seniverse.com"
#define WEB_PORT   "443"
#define WEB_URL    "https://api.seniverse.com/v3/weather/now.json" \
                   "?key=" WEATHER_API_KEY \
                   "&location=" WEATHER_LOCATION \
                   "&language=en&unit=c"

/* HTTP 请求报文 —— 一段纯文本 */
static const char HTTP_REQUEST[] =
    "GET " WEB_URL " HTTP/1.1\r\n"
    "Host: " WEB_SERVER "\r\n"
    "User-Agent: Ai-WB2 XEMOWO\r\n"
    "Accept: application/json\r\n"
    "Accept-Encoding: identity\r\n"
    "Connection: close\r\n"
    "\r\n";

static void https_weather_task(void *pvParameters)
{
    long long t0, t1, t2, t3, t4;

    /* 1. TCP 连接(含 DNS 解析) */
    t0 = aos_now_ms();
    mbedtls_net_connect(&server_fd, WEB_SERVER, WEB_PORT,
                        MBEDTLS_NET_PROTO_TCP);
    t1 = aos_now_ms();

    /* 2. TLS 握手 */
    t2 = aos_now_ms();
    while (mbedtls_ssl_handshake(&ssl) != 0) ;
    t3 = aos_now_ms();

    /* 3. 发送 HTTP 请求 */
    mbedtls_ssl_write(&ssl, HTTP_REQUEST, strlen(HTTP_REQUEST));

    /* 4. 接收 HTTP 响应 */
    char response[4096];
    int total = mbedtls_ssl_read(&ssl, response, sizeof(response));
    t4 = aos_now_ms();

    /* 解析 JSON,提取天气 */
    cJSON *root = cJSON_Parse(extract_body(response));
    char *city  = cJSON_GetObjectItem(root, "results[0].location.name");
    char *text  = cJSON_GetObjectItem(root, "results[0].now.text");
    char *temp  = cJSON_GetObjectItem(root, "results[0].now.temperature");

    /* 打印天气 + 各层耗时 */
    printf("| API  | City        | %s |\n", city);
    printf("| API  | Weather     | %s |\n", text);
    printf("| API  | Temperature | %s C |\n", temp);
    printf("| TCP  | Connect     | %lld ms |\n", t1 - t0);
    printf("| TLS  | Handshake   | %lld ms |\n", t3 - t2);
    printf("| HTTP | Req/Res     | %d/%d bytes |\n", req_len, total);
    printf("| HTTP | Latency     | %lld ms |\n", t4 - t3);
    printf("| ALL  | Total RTT   | %lld ms |\n", t4 - t0);
}

📊 实际运行输出

graph LR A[🔵 WB2] -->|"TCP Connect 234ms"| B[📡 服务器] B -->|"TLS Handshake 1890ms"| C[🔐 加密通道] C -->|"HTTP Request 244B"| D[📤 GET /weather] D -->|"HTTP Response 671B"| E[📥 200 OK + JSON] E -->|"cJSON 解析"| F[☁️ 天气展示]
+------+------------------+------------------+
| TYPE |       ITEM       |      VALUE       |
+------+------------------+------------------+
| API  | City            | Shenzhen         |
| API  | Weather         | Cloudy           |
| API  | Temperature     | 30             C |
| TCP  | Connect time    |   234 ms         |
| TLS  | Handshake time  |  1890 ms         |
| HTTP | Request size    |   244 bytes      |
| HTTP | Response size   |   671 bytes      |
| HTTP | Server latency  |   312 ms         |
| ALL  | Total RTT       |  2436 ms         |
+------+------------------+------------------+

各字段说明

层级 表头 含义 代码对应
API City 城市名 JSON:location.name
API Weather 天气现象 JSON:now.text
API Temperature 当前气温 JSON:now.temperature
TCP Connect time DNS 解析 + TCP 三次握手耗时 mbedtls_net_connect() 前后计时
TLS Handshake time 证书验证 + 密钥协商耗时 mbedtls_ssl_handshake() 前后计时
HTTP Request size GET 请求报文字节数 strlen(HTTP_REQUEST)
HTTP Response size 服务器返回总字节数 mbedtls_ssl_read() 累计
HTTP Server latency 从发完请求到收完响应的时间 发→收 计时差
ALL Total RTT 端到端完整耗时 前三行之和

🆚 五、TCP vs TLS vs HTTP 一句话对比

是什么 干什么 在代码里
TCP 传输管道 把字节从 A 送到 B,保证不丢不乱 mbedtls_net_connect()
TLS 加密保险箱 在 TCP 管道上套一层加密,防窃听 mbedtls_ssl_handshake()
HTTP 数据格式 定义请求/响应的语法和语义 "GET /weather HTTP/1.1\r\n..."
    你写的文本                实际传输过程
    ─────────                ────────────
    "GET /weather"  ──→ [TLS 加密] ──→ [TCP 分段] ──→ [WiFi 发送]
                                                 ↓
    {"text":"Cloudy"} ←── [TLS 解密] ←── [TCP 重组] ←── [WiFi 接收]

📝 六、编译 & 烧录

cd applications/xemowo/XEMOWO_TEST2
export BL60X_SDK_PATH=~/Ai-Thinker-WB2

make -j8                                  # 编译

make flash p=/dev/ttyUSB0 b=921600        # 烧录

✅ 七、你学到了什么

  • HTTP 是一段纯文本格式约定,不是神秘的东西
  • TCP 是传输管道——DNS 解析 + 三次握手 + 可靠传输
  • TLS 在 TCP 之上加了一层加密——证书验证 + 密钥协商
  • HTTPS = HTTP over TLS over TCP
  • 每一层的耗时都可以用 aos_now_ms() 精确测量
  • mbedTLS 是一个轻量 C 库,能在 RISC-V MCU 上跑完整 TLS 1.2

🚀 八、和 MQTT 对比

维度 HTTP (XEMOWO_TEST2) MQTT (XEMOWO_TEST1)
模型 请求/响应 发布/订阅
谁主动 客户端拉 服务器推
连接 每次请求建一次 TCP+TLS 长连接,复用 TCP
每次耗时 ~2400ms(TCP+TLS+传输) <50ms(已连接状态下)
适合 定时查询、API 访问 实时消息、传感器上报

两个工程都在 applications/xemowo/ 下。一个拉,一个推。跑完两个,HTTP 和 MQTT 的区别用眼睛就能看到。


"HTTP is just text over TCP. HTTPS is the same text, encrypted."

你刚刚用 mbedTLS 和一块 RISC-V 芯片,亲手验证了这句话。


Ai-WB2 (BL602 RISC-V) · mbedTLS · 心知天气 API · 代码: applications/xemowo/XEMOWO_TEST2/

──── 0人觉得很赞 ────

使用道具 举报

您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 31193 个
  • 话题数: 42275 篇