全局契约
回调参数中的指针 / 视图(XS_HttpReq、头结构、消息视图)只在回调栈内有效;值可带出,指针必须先拷贝。
ServiceUnit 在一代的生命周期内至多执行一次;未初始化完成的候选不会误调 Unit。
14 个符号按需导出。不导出 RequestProc 的 host 就是纯静态站;未导出 WsText/WsBinary 的 ws host 返回 503。
线程分布一览:ServiceInit / ServiceSwap 在装配或 reload 控制线程;RequestProc / Ws* / Event* 在引擎 worker 线程(可并发);ServiceUnit 在 generation GC 线程。跨线程共享状态自行同步。
生命周期回调(3)
ServiceInit 生命周期
本代脚本装载完成后调用一次——建路由表、开数据库、初始化静态状态的地方。
新代必须 Init 完成才对外可见;Init 里取交接数据用 xsSwapTake(见 XServer API)。
static void ServiceInit(XS_HostInfo* pHost)
{
DB_Init(); /* 打开 SQLite、建表 */
Page_Init();
Template_Init();
RouteHTTP_Init(); /* 注册并编译路由 */
}
ServiceUnit 生命周期
本代退役时的析构——按 Init 的逆序释放。全生命周期至多执行一次。
触发点有两个:进程优雅停机路径,或热重载后旧代最后一个租约归还。Init 未完成过的代不会调用 Unit。
static void ServiceUnit(XS_HostInfo* pHost)
{
RouteHTTP_Unit(); /* 释放 pattern 与路由表 */
Template_Unit();
Page_Unit();
DB_Unit(); /* 关闭数据库 */
}
ServiceSwap 生命周期
换代前导出跨代状态的无破坏快照;新代 ServiceInit 内经 xsSwapTake 取回。
| 参数 | 方向 | 说明 |
|---|---|---|
pHost | 输入 | 即将退役的旧代主机 |
ppShared | 输出 | 接收 xvalue* 快照;所有权移交宿主转交新代 |
无破坏的含义:导出快照后旧代仍可能继续服务(极端情况下提交还会被取消)——不要在 Swap 里关闭资源。
static bool ServiceSwap(XS_HostInfo* pHost, xvalue** ppShared)
{
xvalue* pState = xrtValueObject();
xrtValueObjectSetNew(pState, XRT_STR_LITERAL("counter"),
xrtValueInt64(G_iCounter));
*ppShared = pState;
return true;
}
HTTP 回调(1)
RequestProc HTTP
每个 HTTP 请求的入口。返回三态声明"谁负责这个请求的余生"。
| 返回值 | 语义 | 驱动随后行为 |
|---|---|---|
XS_OK(0) | 完整响应已写出 | 消费 body 余量,继续 keep-alive |
XS_FALLBACK(1) | 未处理 | GET/HEAD 落静态层,其余 404 |
XS_TAKEOVER(2) | 接管整条连接 | 撤出驱动;应用自行收发并最终 Close |
XS_HttpReq 是视图结构体:tcp/tls 二选一非空(xrt 全套流 API 可用)、head 解析后的请求头(含 MethodCode)、body 分帧状态机、host/server 归属。字段逐条见 结构体参考(规划中)。
/* demo 的路由框架最终都收敛到 RequestProc */
static XS_RequestResult RequestProc(XS_HttpReq* pReq)
{
if ( RouteHTTP_Dispatch(pReq) ) return XS_OK;
return XS_FALLBACK; /* 未命中 → wwwroot */
}
WebSocket 回调(6)
XServer 完成握手校验与 xrtWsStreamAttach;掩码、分片重组、控制帧、permessage-deflate 全部在 xrt 层处理。发送用 xrtWsStreamText / Binary 族。
WsOpen WebSocket
连接建立(101 完成、流附加后)触发。
static void WsOpen(XS_HostInfo* pHost, xwsstream* pWs)
{
(void)xrtWsStreamText(pWs, xrtStrView("connected"));
}
WsText WebSocket
整条文本消息重组完成后触发;tText 为本回调内有效的视图。
static void WsText(XS_HostInfo* pHost, xwsstream* pWs, xstrview tText)
{
(void)xrtWsStreamText(pWs, tText);
}
WsBinary WebSocket
整条二进制消息触发;累计超过 ws_message_limit 以 close 1009 结束连接。
WsPing WebSocket
收到 Ping 帧。Pong 的自动回应由 xrt 层处理——此回调用于业务观察(心跳统计等)。
WsPong WebSocket
收到 Pong 帧——测量往返延迟的位置。
WsClose WebSocket
连接关闭;携带状态码与最多 123 字节 UTF-8 原因视图。
| 常见 iCode | 含义 |
|---|---|
1000 | 正常关闭 |
1009 | 消息超限(ws_message_limit) |
1011 | 服务端内部错误(如 OOM) |
TCP 流回调(3)
XS_StreamConn 是视图结构体:tcp 与 tls 二选一非空,按非空一侧用对应发送 API(tcps 下禁止绕过 tls 直写)。连接生命周期由宿主持有——应用不负责 Destroy。
EventOpen TCP
流连接建立后触发(发欢迎横幅的时机)。
static void EventOpen(XS_HostInfo* pHost, XS_StreamConn* pConn)
{
if ( pConn->tcp != NULL )
(void)xrtNetStreamSend(pConn->tcp, "hello\n", 6);
}
EventData TCP
数据到达。pBuffer 是零拷贝缓冲链(回调内借用),尺寸查询 xrtNetBufSize,数据经 xrt 缓冲 API 消费。
EventClose TCP
连接关闭终态;含网络结果码与可选错误对象(借用)。
UDP 回调(1)
EventDgram UDP
每个数据报触发一次;无连接状态,每个报文都经监听槽位取当前代 lease。
| pMsg 字段 | 说明 |
|---|---|
Remote | 来源地址(xrtNetAddr 族转换文本) |
Data / Size | 负载与长度 |
Flags | XNET_UDP_MESSAGE_TRUNCATED 等 |
static void EventDgram(XS_HostInfo* pHost, xnetudp* pUdp,
const xnetudpmessage* pMsg)
{
(void)xrtNetUdpSendTo(pUdp, &pMsg->Remote, "ack", 3);
}