公共类型决定整个协议栈能表达什么,GVL 常量决定它能承受多大的报文和多少连接。先公开这些文件,后续阅读 Parser、Server 和 Client 才有统一坐标。
适合谁收藏
- 准备复用本组源码并审查对象边界的工程师。
- 需要把公开代码装配进目标 CodeSys 工程的人。
- 准备重新完成编译、离线测试和真机验证的读者。
本篇完整公开 5 个 ST 文件。代码直接读取已验证工程,保留声明、实现、注释和缩进;没有伪代码,没有跨文件拼接,也没有省略号。
先给结论
公共类型决定整个协议栈能表达什么,GVL 常量决定它能承受多大的报文和多少连接。先公开这些文件,后续阅读 Parser、Server 和 Client 才有统一坐标。 本篇的通过标准不是“代码已经贴出”,而是每个文件的职责、调用位置、状态边界和验证入口都能对应起来,并且完整代码可逐字回查源文件。

读图重点
先找到 E_HttpError 在本组中的位置,再沿图确认其余对象分别承担数据、状态、执行或诊断职责。图只给阅读顺序,最终判断必须回到下面的完整 ST 代码。
先看文件职责
| 序号 | 文件 | 职责 | 行数 |
|---|---|---|---|
| 1 | E_HttpError.st | 协议栈统一错误枚举 | 27 |
| 2 | E_HttpMethod.st | HTTP 方法枚举 | 16 |
| 3 | GVL_Http.st | 容量、超时和默认值常量 | 25 |
| 4 | ST_HttpRequest.st | 结构化 HTTP 请求 | 20 |
| 5 | ST_HttpResponse.st | 结构化 HTTP 响应 | 17 |
阅读顺序不是按文件名机械展开。先看数据和状态,再看公开方法,最后顺着错误出口和调用对象检查边界。源码篇的目标是让读者能对照工程复现,不是用大段代码制造篇幅。
从协议约束到代码职责
协议约束
公共类型决定整个协议栈能表达什么,GVL 常量决定它能承受多大的报文和多少连接。先公开这些文件,后续阅读 Parser、Server 和 Client 才有统一坐标。 协议层只定义消息与状态成立的条件,工程层还必须把条件分配给确定对象,避免 Parser、Builder、Server、Client 和测试入口互相越权。
对象分工
- 第 1 个对象
E_HttpError.st:承担“协议栈统一错误枚举”。阅读时先确认输入与公开输出,再追状态、长度和错误出口,最后核对它被谁周期调用或被哪个对象消费。 - 第 2 个对象
E_HttpMethod.st:承担“HTTP 方法枚举”。阅读时先确认输入与公开输出,再追状态、长度和错误出口,最后核对它被谁周期调用或被哪个对象消费。 - 第 3 个对象
GVL_Http.st:承担“容量、超时和默认值常量”。阅读时先确认输入与公开输出,再追状态、长度和错误出口,最后核对它被谁周期调用或被哪个对象消费。 - 第 4 个对象
ST_HttpRequest.st:承担“结构化 HTTP 请求”。阅读时先确认输入与公开输出,再追状态、长度和错误出口,最后核对它被谁周期调用或被哪个对象消费。 - 第 5 个对象
ST_HttpResponse.st:承担“结构化 HTTP 响应”。阅读时先确认输入与公开输出,再追状态、长度和错误出口,最后核对它被谁周期调用或被哪个对象消费。
装配与验证
这组文件必须作为一个职责单元阅读和编译。先用确定输入验证“资源边界必须显式”,再制造非法或容量边界验证“请求与响应使用结构体跨层传递”,最后在真实通信或上层调用中确认“错误枚举区分协议、容量和 TCP 故障”。如果单文件测试通过但装配后失败,应优先检查结构体、常量、状态枚举和周期调用关系,而不是立即重写核心算法。源码完整公开只证明读者拿到了同一事实源,目标运行时是否通过仍需重新编译和真机取证。
本篇从 E_HttpError.st 开始审查:先确认“资源边界必须显式”对应的类型、常量或公开输入,再沿 CASE 或方法调用追踪成功路径,随后逐个检查容量、超时和协议错误出口,最后在 ST_HttpResponse.st 对应的结果或装配位置确认错误能被观测、清理并再次执行。这个顺序专门用来区分“算法正确但没有周期调用”“状态能完成但错误被覆盖”和“错误枚举区分协议、容量和 TCP 故障尚未形成验证证据”三类问题。只有本篇源码、装配和验证使用同一组对象与同一组边界,完整开源才具有可复现意义。
本篇完整开源代码
下面按职责顺序给出本篇全部 ST 文件。每个代码块保留完整声明与实现;阅读时把状态、长度、错误出口和调用对象与上面的职责表逐项对照。
完整源码 1:E_HttpError.st
职责:协议栈统一错误枚举
/// 功能 : HTTP 协议栈错误枚举。
/// 库依赖 : 暂无
{attribute 'qualified_only'}
{attribute 'strict'}
TYPE E_HttpError :
(
iNoError := 0,
iNeedMoreData := 1,
iInvalidArgument := 2,
iBufferTooSmall := 3,
iInvalidStartLine := 10,
iInvalidHeader := 11,
iMissingHost := 12,
iDuplicateHost := 13,
iInvalidContentLength := 14,
iTransferEncodingContentLength := 15,
iBodyTooLarge := 16,
iChunkedDecodeFailed := 17,
iUnsupportedTransferEncoding := 18,
iTcpClientFailed := 100,
iTcpServerFailed := 101,
iTcpReadFailed := 102,
iTcpWriteFailed := 103,
iTimeout := 104,
iQueueFull := 105
) INT;
END_TYPE完整源码 2:E_HttpMethod.st
职责:HTTP 方法枚举
/// 功能 : HTTP 方法枚举。
/// 库依赖 : 暂无
{attribute 'qualified_only'}
{attribute 'strict'}
TYPE E_HttpMethod :
(
iUnknown := 0,
iGet := 1,
iHead := 2,
iPost := 3,
iPut := 4,
iDelete := 5,
iPatch := 6,
iOptions := 7
) INT;
END_TYPE完整源码 3:GVL_Http.st
职责:容量、超时和默认值常量
/// 功能 : HTTP 协议栈全局常量。
/// 库依赖 : 暂无
{attribute 'qualified_only'}
VAR_GLOBAL CONSTANT
cnDefaultServerPort : UINT := 8088; // 全局协议常量。
cnMaxClientSlots : UINT := 4; // 全局协议常量。
cnRxBufferSize : UINT := 4095; // 全局协议常量。
cnTxBufferSize : UINT := 4095; // 全局协议常量。
cnMaxMessageSize : UINT := 4095; // 全局协议常量。
cnMaxHeaderSize : UINT := 2047; // 全局协议常量。
cnMaxBodySize : UINT := 1023; // 全局协议常量。
cnMaxTargetLen : UINT := 255; // 全局协议常量。
cnMaxHostLen : UINT := 128; // 全局协议常量。
cnMaxHeaderValueLen : UINT := 255; // 全局协议常量。
cnMaxChunkLineLen : UINT := 32; // 全局协议常量。
cnTcpConnectTimeoutUs : UDINT := 5000000; // 全局协议常量。
cnClientTimeoutMs : UDINT := 8000; // 全局协议常量。
cnServerConnectionMs : UDINT := 8000; // 全局协议常量。
cnWriteTimeout : TIME := T#5S; // 全局协议常量。
cnTcpReadChunkSize : UINT := 240; // NBS 单次 TCP_Read 字节数,避开部分运行时 255 字节边界。
cnTcpWriteChunkSize : UINT := 240; // NBS 单次 TCP_Write 字节数,大响应按 TCP 字节流分批发送。
cnTcpReadMaxErrorCount: UINT := 3; // TCP_Read 连续错误滤波次数,避免大报文半包接收被瞬时读错误误杀。
cnDefaultContentType : STRING(32) := 'text/plain'; // 全局协议常量。
cnDefaultPath : STRING(8) := '/'; // 全局协议常量。
END_VAR完整源码 4:ST_HttpRequest.st
职责:结构化 HTTP 请求
/// 功能 : HTTP 请求结构。
/// 库依赖 : 暂无
TYPE ST_HttpRequest :
STRUCT
eMethod : E_HttpMethod := E_HttpMethod.iUnknown;
sMethod : STRING(16) := '';
sTarget : STRING(GVL_Http.cnMaxTargetLen) := '';
sVersion : STRING(16) := 'HTTP/1.1';
sHost : STRING(GVL_Http.cnMaxHostLen) := '';
sContentType : STRING(96) := '';
sAuthorization : STRING(160) := '';
sAdditionalHeader : STRING(GVL_Http.cnMaxHeaderSize) := '';
sRawHeaders : STRING(GVL_Http.cnMaxHeaderSize) := '';
sBody : STRING(GVL_Http.cnMaxBodySize) := '';
bHasContentLength : BOOL := FALSE;
bTransferChunked : BOOL := FALSE;
bConnectionClose : BOOL := FALSE;
udiContentLength : UDINT := 0;
END_STRUCT
END_TYPE完整源码 5:ST_HttpResponse.st
职责:结构化 HTTP 响应
/// 功能 : HTTP 响应结构。
/// 库依赖 : 暂无
TYPE ST_HttpResponse :
STRUCT
sVersion : STRING(16) := 'HTTP/1.1';
uiStatusCode : UINT := 0;
sReason : STRING(64) := '';
sContentType : STRING(96) := 'text/plain';
sAdditionalHeader : STRING(GVL_Http.cnMaxHeaderSize) := '';
sRawHeaders : STRING(GVL_Http.cnMaxHeaderSize) := '';
sBody : STRING(GVL_Http.cnMaxBodySize) := '';
bHasContentLength : BOOL := FALSE;
bTransferChunked : BOOL := FALSE;
bConnectionClose : BOOL := FALSE;
udiContentLength : UDINT := 0;
END_STRUCT
END_TYPE本篇阅读抓手
- 资源边界必须显式。
- 请求与响应使用结构体跨层传递。
- 错误枚举区分协议、容量和 TCP 故障。
如何验证这组源码
- 先针对
E_HttpError.st的公开输入和错误出口建立确定性用例。 - 再把“资源边界必须显式”转成至少一个正常场景和一个失败场景。
- 本篇 5 个文件必须一起编译,避免只验证单个函数而漏掉数据结构或调用边界。
- 真机复核时重点观察“错误枚举区分协议、容量和 TCP 故障”,并保留对应状态、计数和原始报文。
这一篇你最该记住
- 资源边界必须显式。
- 请求与响应使用结构体跨层传递。
- 错误枚举区分协议、容量和 TCP 故障。
系列导航
- 系列:CodeSys HTTP 系列教程,第 19/28 篇。
- 当前源码加更:第 1/8 篇。
- 本篇完整源码文件数:5。
- 上一篇:第18篇
- 下一篇:第20篇
评论区预留
这里先保留评论和回复结构,不接入第三方服务。后续统一决定登录、匿名、审核、反垃圾和静态站兼容策略。