第 14 章 / 共 51 章
卷三 · 协议开发
HTTP 基础:视图结构与三态返回
RequestProc 收到的不是包装对象,而是一组"可以直接动手"的 xrt 原生指针。本章把这张视图地图画完整——之后四章都在这张地图上作业。
本章导读
站位:卷三的地图章。ch15(响应)、ch16(请求体)、ch17(路由)分别展开视图的不同侧面;本章先建立整体认知与两条铁律(借用、三态)。
14.1 引入
写 HTTP 业务需要三种东西:知道请求是什么(方法、路径、头、体)、知道往哪写响应(传输层)、知道处理完之后谁接管。多数框架把三者揉进一个 Request/Response 对象,用抽象换便利;XServer 把三者拆开直接给你——XS_HttpReq 的六个字段就是这三样东西的地址。
14.2 XS_HttpReq 逐字段
XS_HttpReq(xsbase.h 原文)出处:src/sdk/xsbase.h
typedef struct {
xnetstream* tcp; /* 与 tls 二选一非空:传输层裸指针 */
xtlsstream* tls; /* 可直接使用 xrt 全套流/发送 API */
const xhttp1head* head; /* 含 MethodCode;视图回调内有效 */
xhttp1body* body; /* 分帧状态机:定长 / chunked / 关闭 */
const XS_HostInfo* host;
XS_ServerInfo* server;
} XS_HttpReq;
| 字段 | 用途 | 本 章 用 法 |
|---|---|---|
tcp / tls | 响应出口 | 发送响应字节(ch15 展开) |
head | 请求身份 | MethodCode、路径、字段视图(本章 14.3) |
body | 请求体 | 增量读取(ch16 展开) |
host / server | 归属 | 读拓扑信息、Custom 旋钮 |
为什么没有 Response 字段?——因为响应不是对象,是你写进传输层的字节流。这正是"零包装"的彻底之处:没有隐藏的响应缓冲,也就没有"框架什么时候 flush"这类问题。
14.3 请求头读取
方法、路径与字段
static XS_RequestResult RequestProc(XS_HttpReq* pReq)
{
/* 方法:位掩码,既是单方法也是集合元素(ref-enums)*/
if ( pReq->head->MethodCode == XHTTP_METHOD_GET ) { ... }
/* 路径与字段视图:xstrview = 指针 + 长度,回调内有效 */
/* 具体取值 API(字段查找 / 路径分解)见 xrt · http1 参考 */
return XS_FALLBACK;
}
两条读头铁律:第一,head 的字段视图只在本回调栈内有效——XServer 在 PinHead 阶段拷贝了请求头防止 ring-buffer 复用,但换代/请求结束后仍然失效;第二,比较路径不要用 C 字符串函数——视图带长度,按长度比较(xrtStrView 系工具)。
14.4 调用时机与线程
连接建立 → 请求头解析完成 → RequestProc(worker 线程,可并发)
│
┌────────────────────┼────────────────────┐
▼ XS_OK ▼ XS_FALLBACK ▼ XS_TAKEOVER
驱动消费 body 余量 GET/HEAD → 静态层 应用接管连接
继续 keep-alive 循环 其余 → 404 (ch25)
- 每请求一次;keep-alive 连接上逐请求调用
- workers 并发——RequestProc 必须可重入(无跨请求可变静态状态,或自行加锁)
- 驱动与脚本之间有字节消费同步校验:你声明的消费量与线路实际不符即断连——把脚本当不可信边界对待
14.5 契约
- 借用线:六个字段全部回调内有效;值可拷贝带走,指针不行。
- 三态线:XS_OK 前必须写完响应;写过一个字节就不能 FALLBACK;TAKEOVER 后驱动撤出。
- 并发线:RequestProc 在 workers 上并发执行,可重入是硬要求。
常见错误
用 strcmp 比较路径视图
- 症状
- 偶发路径判断错误,尤其路径含查询串或非零结尾缓冲。
- 原因
- xstrview 不是 C 字符串——它可能不带 NUL 终止,长度才是权威。
✗ 错误
if ( strcmp(pPath, "/api") == 0 )✓ 正确
/* 按视图长度比较(xrtStrView 工具)*/RequestProc 里放了跨请求可变静态
- 症状
- 并发下计数错乱、偶发崩溃。
- 原因
- 忘了 workers 并发——静态变量被多个请求同时读写。
编程练习
基础方法分诊台
写 RequestProc:GET 打印 "GET"、POST 打印 "POST",其余返回 XS_FALLBACK。
验收:三种方法各测一次,日志与回落行为符合预期。
进阶并发安全计数
统计已处理请求数(提示:原子操作,xrtAtomic 族)。
验收:压测 1 万请求后计数 = 1 万,无丢失无撕裂。
挑战视图生命周期实证
把 head 的某个视图指针存全局,下一个请求再读——观察并解释现象;然后改成回调内拷贝。
验收:能按第 3 章的代/借用模型解释崩溃或错乱的原因。
小结
| 要点 | 结论 |
|---|---|
| 视图结构 | tcp/tls(出口)+ head(身份)+ body(体)+ host/server(归属) |
| 无 Response 对象 | 响应是写进传输层的字节流(ch15) |
| 读头铁律 | 视图回调内有效;按长度比较,不当 C 字符串 |
| 并发 | workers 可重入;消费量与线路同步校验 |
本章涉及的 API 参考
xrt 延伸阅读
- xrt 参考 · http1 — xhttp1head 字段视图与头查找 API 全集
- xrt 参考 · string — 视图比较与安全字符串工具