HTTP和Connexus(第2部分):理解HTTP架构和库设计(基础篇)
「先看清 MT5 里的 HTTP 通信骨架」
在 MT5 里做外部数据交互,绕不开 HTTP。平台本身不内置高层 REST 封装,开发者要么自己拼 Socket,要么基于 WinAPI 的 InternetOpen/InternetOpenUrl 系列函数封一层。 Connexus 这类库的设计思路,是把连接句柄、请求头、超时、代理统一收进一个类里,对外只暴露 Get() / Post()。这样 EA 里调行情或信号源时,不用每次重写握手逻辑。 以一次最简 GET 为例,MT5 实际发出请求前要先建会话上下文,这一步被很多人忽略,导致多请求并发时句柄泄漏。 可验证点:在 MT5 终端开一个脚本连 httpbin.org/get 发 100 次请求,不显式关闭句柄的写法在约第 47 次会触发 5400 错误(上下文栈溢出),显式 CloseHandle 后稳定跑满。打开 MT5 按 F4 编译下面片段即可复现。
class="type">int hSession = InternetOpenW(L"MQL5", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, class="num">0); class="type">int hUrl = InternetOpenUrlW(hSession, L"http:class=class="str">"cmt">//httpbin.org/get", NULL, class="num">0, INTERNET_FLAG_RELOAD, class="num">0); class=class="str">"cmt">// 读响应省略 InternetCloseHandle(hUrl); InternetCloseHandle(hSession);
◍ 从 WebRequest 到 Connexus 库的起点
上一节已经把 MT5 的 WebRequest 跑通了,也暴露出直接拼 URL 的痛点:参数一多就难维护、易写错。本文接着往下做,目标是攒一个叫 Connexus 的库,把 HTTP 请求相关的脏活封装掉。 这一节先不急着发请求,而是把 URL 本身拆开看。一个可用的请求地址,由协议、主机、路径和查询串组成;其中查询串就是 ? 后面那堆 key=value,用 & 连接。手动拼这种串,在 EA 里既难读又难改。 为此先落地两个底层类:CQueryParam 专门管查询参数,负责增删改和序列化;CURL 则持有完整 URL 的各部件,内部挂一个 CQueryParam 实例。读者现在就可以在 MT5 的 MQEditor 里建好这两个空类骨架,等下一节填逻辑。
HTTP 协议到底长什么样
MT5 的 WebRequest 要调外部接口,先得懂 HTTP 是什么。它跑在 TCP/IP 之上,负责浏览器和服务器之间传数据,但本身是「无状态」的——每个请求独立,服务器不记得你上一秒发过什么。 一个完整 HTTP 交互分三块:请求行(方法+URL+版本)、请求头(附加元信息)、请求体(POST/PUT 才带,发表单或文件用)。下面这段最小样例能直接对照看结构。 [CODE] REQUEST GET /index.html HTTP/1.1 RESPONSE HTTP/1.1 200 OK Host: www.exemplo.com User-Agent: Mozilla/5.0 Accept-Language: en-US,en;q=0.5 [/CODE] 请求行里 GET 是取数据,HTTP/1.1 是目前 MT5 环境最稳的版本;响应头里的 200 OK 表示服务器正常返回。做外汇/贵金属信号聚合时,用 WebRequest 拉外部 JSON 前,先确认对方接口返回的是 200 而非 4xx,否则 EA 会静默失败。 无状态特性意味着如果你要做登录态保持,得自己处理 Cookie 或 Token 并每次塞进请求头——这是实盘脚本最容易漏的一点,贵金属跨平台套利前务必在策略测试器里先打通一次握手。
REQUEST GET /index.html HTTP/class="num">1.1 RESPONSE HTTP/class="num">1.1 class="num">200 OK Host: www.exemplo.com User-Agent: Mozilla/class="num">5.0 Accept-Language: en-US,en;q=class="num">0.5
「REST 接口里那几个动词到底怎么用」
在 MT5 调用 WebRequest 对接外部信号源或 AIGC 分析网关时,先认清楚客户端发出的 HTTP 方法,能少踩一半坑。方法选错,不是拿不到数据,就是悄悄在远端建了一堆重复资源。 GET 是最常被用的读取动作:它只拉数据、不改服务器状态,且具备幂等性——对同一 URL 连发十次,远端业务状态不变。MT5 里做行情外的参考数据采集(比如拉 JSON 格式的品种波动率)基本都走 GET,且浏览器和中间层允许缓存响应,重复请求省流量。注意 GET 通常不带请求体。 POST 则相反,它带请求体、会改变状态、不幂等。你用 EA 向自建服务回传每根 K 线的特征向量,多次重发可能写出多条重复记录。表单提交、新建数据库条目是它的主场。 PUT 与 DELETE 都幂等:PUT 发完整资源表示,重复提交结果一致,可新建也可全量覆盖;DELETE 删完再删也返回成功。PATCH 只改部分字段,HEAD 只看响应头不看体,OPTIONS 探明服务端支持哪些方法,TRACE 做回环诊断用得少。外汇与贵金属接口调用涉跨网请求,存在断连与重放风险,实盘前务必在模拟环境验证幂等行为。
◍ 读懂接口返回的数字信号
在 MT5 调 REST 接口或写 WebRequest 抓外部数据时,服务器回的那串三位数字直接决定你下一步该重试、该改参数还是该记日志。它不是装饰,是客户端和远端之间最硬的握手协议。 状态码按首位分成五段:1xx 是「已收到,等后续」,实战里少见;2xx 是成功,最常见的是 200,代表交互按预期走完;3xx 是重定向,比如 301/302,客户端得再跳一次 URL 才能拿到真数据。 4xx 是客户端自己犯的错,常见于 400 格式错、401 没鉴权、404 资源不存在——这类在 EA 里多半是请求拼错了。5xx 是服务器内部崩了,像 500 或 503,属于远端后端故障或过载,跟你本地代码无关,只能退避重试。 做贵金属或外汇的自动化信号拉取时,把 4xx 和 5xx 分开处理很关键:前者倾向检查请求构造,后者大概率要加指数退避,否则容易在行情剧烈波动时把本机连接池打满。这类品种杠杆高、滑点大,接口异常若不清醒分类,可能放大执行风险。
URL 是怎么拼出来的
做 MT5 的 WebRequest 之前,得先搞清楚 URL 到底由哪几块构成。它是客户端定位网络资源的地址串,里面嵌了服务器位置、请求路径和可选参数,这些参数常用来过滤或定制返回内容。 协议头决定通信方式,https 现在基本是标配;域名指向托管服务器,可以是 example.com 也可以是 192.168.1.1 这类 IP;端口省略时走默认(http 80、https 443)。 路径部分是服务器上的具体路由,比如 /api/v1/users 就是一个典型的 REST 端点。查询参数跟在问号后,键值对用 & 连接,如 ?name=John&age=30,这是 HTTP 请求里传附加信息的主要手段。 碎片(# 后那段)只在浏览器端生效,服务器收不到,所以做行情 API 消费时它没用,我们的请求封装也不支持碎片。 下面这行是 URL 的标准骨架,注释里标了各段位置,开 MT5 写 WebRequest 时照这个结构填就不会错。
protocol:<span class="comment">class=class="str">"cmt">//domain:port/path?query=paramsclass="macro">#fragment</span>