HTTP和Connexus(第2部分):理解HTTP架构和库设计·进阶篇
🧩

HTTP和Connexus(第2部分):理解HTTP架构和库设计·进阶篇

(2/3)· 搞懂URL拆解与请求三件套,才能把WebRequest的坑提前埋进类里

实战向进阶 第 2/3 篇
很多交易者直接把WebRequest塞进EA主循环,一旦URL拼错或参数重复就整段失效。把HTTP当黑盒用,只会让接口调试变成玄学。理清请求行、头、体的边界,是写稳定行情外联的第一步。

「从一条 URL 拆出可程序化的请求结构」

以一条典型行情接口地址为例:协议为 https,域名 www.example.com,端口 8080,路径 /market/symbols,查询参数 active=EURUSD&timeframe=h1。把这段拆开看,外汇 EURUSD 与周期 h1 都以键值对形式挂在问号之后,意味着行情请求本质是可被代码拼装的字符串。 在 MT5 上做 AIGC 式行情拉取时,硬编码地址很难复用。更稳的做法是把协议、域名、端口、路径、参数各自存为变量,由类方法动态拼接。这样切换黄金 XAUUSD 或切到 m5,只改参数不改结构。 下面这段是原文给出的地址示例,注意 & 在代码注释里写作 &amp; 是 HTML 转义,MQL5 字符串里直接用 & 即可: [CODE] https:<span class="comment">//www.exemplo.com:8080/market/symbols?active=EURUSD&amp;timeframe=h1</span> [/CODE] 构建 Connexus 库的第一层,就落在负责 URL 与查询参数操作的类上。先写能增删参数的方法,后面接行情接口时才不会每次手拼字符串、漏写端口。外汇与贵金属接口调用涉及实时网络请求,存在连接失败与数据延迟的高风险,参数拼错往往直接返回空响应。

MQL5 / C++
https:<span class="comment">class=class="str">"cmt">//www.exemplo.com:class="num">8080/market/symbols?active=EURUSD&amp;timeframe=h1</span>

◍ 用 CUrl 与 CJson 管住查询参数

做 MT5 下的 WebRequest 调用,最烦的是手工拼 query string。这一节先把底层骨架立起来:建一个 CUrl 类,专职拼基础地址、挂参数、输出完整 URL,不让散字符串在代码里乱飞。 参数管理另起一个 CJson 类。它干的事很具体——把原本挤在 URL 里的 ?a=1&b=2 这类查询串,转成结构化 JSON。这样后续增删字段不用正则去切字符串,直接按键值读写,出错概率低得多。 实际验证路径:在 MT5 里新建这两个类,随便喂一个 "symbol=EURUSD&tf=M15" 的参数字符串给 CJson,看它吐出的 JSON 对象是否字段齐全。外汇与贵金属行情接口调用本身属高风险操作,参数错一处就可能拿到空响应。

先搞清JSON长什么样

在MT5里用CJson类解析外部信号前,得先认得JSON这种结构。它是网页端传结构化数据最常用的轻量格式,本质就是一组被大括号{}包起来的键值对,键和值之间用冒号隔开,多对之间用逗号分开。 你可以把它和URL里的查询参数对照着看:?name=John&age=30 里 name 是键、John 是值,JSON不过是把这种关系用更规整的嵌套文本写出来,方便程序直接反序列化。 下面这段就是一个最直白的例子,三个键 name、age、city 各自带一个值,没有层级嵌套,适合先拿来做解析练习。

MQL5 / C++
{
  "name": "John",
  "age": class="num">30,
  "city": "New York"
}

「用 CJson 把查询参数结构化」

在 MT5 里拼 REST 请求时,很多人直接手写 ?name=John&age=30 这种参数字符串。参数一多,拼接、改值、校验都很易错,可读性也差。 CJson 类的价值是把这些参数先收进一个结构化对象,再序列化成 JSON 塞进 URL 或请求体。组织、读取、验证都更干净,后续发送和接收数据也能复用同一套逻辑。 实际落地:开 MT5 新建 EA,include 进 CJson 相关头文件,先试着把 3 个字符串参数转成 JSON 文本,确认输出格式无误再接接口。外汇与贵金属接口调用涉及账户与行情风险,参数错配可能导致请求被拒或异常下单。

◍ 搭好 Connexus 的头文件骨架

在 MetaEditor 里先把目录层级建清楚,否则后面 include 路径会反复报错。具体做法是在 includes 下新建 Connexus 文件夹,其下再分 Data 与 URL 两个子目录。 Data 里放 Json.mqh(文末附带的 CJson 类),URL 里放 QueryParam.mqh 与 URL.mqh。CJson 的实现细节不用深究,接口很直白,重点是把物理路径对齐。 最终目录树应如下,少一个文件编译都会失败:

MQL5 / C++
MQL5
 |--- include
 |--- |--- Connexus
 |--- |--- |--- Data
 |--- |--- |--- |--- Json.mqh
 |--- |--- |--- URL
 |--- |--- |--- |--- QueryParam.mqh
 |--- |--- |--- |--- URL.mqh

封装查询参数的键值管理类

在 MT5 里拼 REST 请求前,先把零散的查询参数收拢到一个类里更稳妥。CQueryParam 内部挂了一个私有的 CJson 对象 m_query_param,所有参数以键值对形式存在这张表里,避免手动拼字符串时漏掉 & 或 =。 对外暴露的方法覆盖了增删查与序列化:AddParam 有两个重载,一个收 key/value 两个入参,另一个直接吃 key=value 形态的整串,遇到 = 才切分;AddParams 用字符串数组批量灌入,本质是对数组每项调一遍单参版 AddParam。 RemoveParam 按 key 摘掉某条;GetParam 按 key 返回值;HasParam 探一下 key 在不在;ParamSize 回传当前条目数。Parse 吃一整条 query 字符串,按 & 切参数、按 = 切键值后写进 m_query_param;Serialize 反向把表里内容拼回 key=value&... 形态,供 WebRequest 直接带出去。Clear 清空复位。 下面这段是类的骨架声明,注意头里要自己补 CJSON 的导入语句才能编译过。开 MT5 建个 include 试一下,先 AddParam("symbol","XAUUSD") 再 Serialize,应该得到 symbol=XAUUSD——外汇贵金属行情接口调用失败,多半是参数没序列化对,杠杆和高波动风险自己掂量。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| class : CQueryParam                                                     |
class=class="str">"cmt">//|                                                                        |
class=class="str">"cmt">//| [PROPERTY]                                                             |
class=class="str">"cmt">//| Name      : CQueryParam                                                |
class=class="str">"cmt">//| Heritage  : No heritage                                                |
class=class="str">"cmt">//| Description : Manages query parameters for HTTP requests               |
class=class="str">"cmt">//|                                                                        |
class=class="str">"cmt">//+------------------------------------------------------------------+
class CQueryParam
  {
class="kw">private:
  CJson                m_query_param;                                        class=class="str">"cmt">// Storage for query parameters
class="kw">public:
                      CQueryParam(class="type">void);
                     ~CQueryParam(class="type">void);
  class=class="str">"cmt">//--- Functions to manage query parameters
  class="type">void                AddParam(class="type">class="kw">string key, class="type">class="kw">string value); class=class="str">"cmt">// Add a key-value pair
  class="type">void                AddParam(class="type">class="kw">string param);                     class=class="str">"cmt">// Add a single key-value parameter
  class="type">void                AddParams(const class="type">class="kw">string &params[]);  class=class="str">"cmt">// Add multiple parameters
  class="type">void                RemoveParam(const class="type">class="kw">string key);             class=class="str">"cmt">// Remove a parameter by key
  class="type">class="kw">string              GetParam(const class="type">class="kw">string key) const;   class=class="str">"cmt">// Retrieve a parameter value by key
让小布替你跑这套
这些诊断小布盯盘的AIGC已内置,打开对应品种页即可看到接口请求是否异常。把重复劳动交给小布,你专注决策。

常见问题

无状态意味着每次WebRequest都是独立会话,服务端不保留上下文。你需在每次请求里带全鉴权与参数,否则可能拿到拒绝响应或旧数据。
可以,小布盯盘的AIGC模块会标记品种页中的外部接口异常,省去你手动打印调试信息。把重复劳动交给小布,你专注决策。
CQueryParam只管键值对拼接与编码,CURL聚合协议、主机、路径与参数实例。分层后改URL结构不必动参数逻辑,利于后续扩展POST体。
GET倾向拉取公开报价且可缓存,POST用于上报订单或订阅信号会改服务端状态。外汇贵金属波动大、高风险,接口选错可能重复下单。