Connexus入门(第一部分):如何使用WebRequest函数?·进阶篇
🌐

Connexus入门(第一部分):如何使用WebRequest函数?·进阶篇

(2/3)· 为什么原生WebRequest在真实API对接中频频卡壳,以及Connexus库如何把底层通信变透明

偏理论进阶 第 2/3 篇
很多开发者以为在MQL5里调一次WebRequest就能直接拉到外部行情,结果卡在header拼错、JSON乱码或超时无提示。先把协议层的三四个暗坑认清楚,后面写库才不至于反复返工。

在 MT5 里发出第一笔 HTTP 请求

想在 EA 或脚本里拉取外部行情接口、把信号推到自有服务,第一步是先跑通 MQL5 的 WebRequest。下面这段初始化函数用 GET 方法打向 httpbin.org 的测试地址,timeout 设 5000 毫秒,也就是最多等 5 秒。 实盘日志里能看到返回 Status code: 200,说明请求成功;响应体被 CharArrayToString 转成字符串后打印出来,包含 headers 里的 User-Agent 为 MetaTrader 5 Terminal/5.4476 (Windows NT 11.0.22631; x64),证明 MT5 终端确实以该身份发起了连接。 把 method 改成 POST、url 换成 https://httpbin.org/post,其余变量不动,就能验证写操作的连通性。外汇与贵金属交易接口调用涉及网络与账户风险,返回非 200 时应倾向先排查 URL 与经纪商权限,而非盲目重试。

MQL5 / C++
class="type">class="kw">string method = "GET";                      class=class="str">"cmt">// HTTP verb in class="type">class="kw">string (GET, POST, etc...)
class="type">class="kw">string url = "https:class=class="str">"cmt">//httpbin.org/get";      // Destination URL
class="type">class="kw">string headers = "";                         class=class="str">"cmt">// Request header
class="type">int timeout = class="num">5000;                         class=class="str">"cmt">// Maximum waiting time class="num">5 seconds
class="type">char data[];                                class=class="str">"cmt">// Data we will send(body) array of type class="type">char
class="type">char result[];                              class=class="str">"cmt">// Data received as an array of type class="type">char
class="type">class="kw">string result_headers;                      class=class="str">"cmt">// String with response headers

class=class="str">"cmt">//--- Calling the function and getting the status_code
class="type">int status_code = WebRequest(method,url,headers,timeout,data,result,result_headers);

class=class="str">"cmt">//--- Print the data
Print("Status code: ",status_code);
Print("Response: ",CharArrayToString(result)); class=class="str">"cmt">// We use CharArrayToString to display the response in class="type">class="kw">string form.
class=class="str">"cmt">//---
class="kw">return(INIT_SUCCEEDED);
}

「POST 请求里字符串被塞进 form 的坑」

在 MT5 里用 WebRequest 发 POST,如果直接把 JSON 字符串丢进 data 数组而不显式声明 Content-Type,服务端大概率不会把它当 json 解析。上面这段实测回显里,body 写成 {"key1":"value1","key2":"value2"} 后,httpbin.org 把它收进了 form 字段,键名带着尾部的 \u0000 空字符,json 字段则是 null。 回测日志里状态码返回 200,Content-Length 被终端算成 34 字节,Content-Type 默认成了 application/x-www-form-urlencoded。这说明 StringToCharArray 用 CP_UTF8 转换时把结尾的 \0 也带进了数组,服务端按表单格式读了。 要拿干净 JSON 响应,得在 headers 里手动加 "Content-Type: application/json",并且确认 WebRequest 的 headers 参数不是空串。外汇与贵金属行情接口若走这套逻辑,网络超时和返回异常都会放大杠杆风险,参数 timeout 建议按 broker 实际延迟调,而非照抄示例。

MQL5 / C++
  class="type">char data[];                                        class=class="str">"cmt">// Data we will send(body) array of type class="type">char
  class="type">char result[];                                       class=class="str">"cmt">// Data received as an array of type class="type">char
  class="type">class="kw">string result_headers;                               class=class="str">"cmt">// String with response headers
class=class="str">"cmt">//--- Treating body
  class="type">class="kw">string body = "{\"key1\":\"value1\",\"key2\":\"value2\"}";
  StringToCharArray(body,data,class="num">0,WHOLE_ARRAY,CP_UTF8); class=class="str">"cmt">// Converts a class="type">class="kw">string to a byte array
class=class="str">"cmt">//--- Calling the function and getting the status_code
  class="type">int status_code = WebRequest(method,url,headers,timeout,data,result,result_headers);

class=class="str">"cmt">//--- Print the data
  Print("Status code: ",status_code);
  Print("Response: ",CharArrayToString(result)); class=class="str">"cmt">// We use CharArrayToString to display the response in class="type">class="kw">string form.

class=class="str">"cmt">//---
  class="kw">return(INIT_SUCCEEDED);
  }
WebRequest(WINV24,M1)  Status code: class="num">200
WebRequest(WINV24,M1)  Resposta: {
WebRequest(WINV24,M1)    "args": {},
WebRequest(WINV24,M1)    "data": "",
WebRequest(WINV24,M1)    "files": {},
WebRequest(WINV24,M1)    "form": {
WebRequest(WINV24,M1)      "{\"key1\":\"value1\",\"key2\":\"value2\"}\u0000": ""
WebRequest(WINV24,M1)    },
WebRequest(WINV24,M1)    "headers": {
WebRequest(WINV24,M1)      "Accept": "*/*",
WebRequest(WINV24,M1)      "Accept-Encoding": "gzip, deflate",
WebRequest(WINV24,M1)      "Accept-Language": "pt,en;q=class="num">0.5",
WebRequest(WINV24,M1)      "Content-Length": "class="num">34",
WebRequest(WINV24,M1)      "Content-Type": "application/x-www-form-urlencoded",
WebRequest(WINV24,M1)      "Host": "httpbin.org",
WebRequest(WINV24,M1)      "User-Agent": "MetaTrader class="num">5 Terminal/class="num">5.4476 (Windows NT class="num">11.0.class="num">22631; x64)",
WebRequest(WINV24,M1)      "X-Amzn-Trace-Id": "Root=class="num">1-66d9bc77-314c004a607c383b3197c15a"
WebRequest(WINV24,M1)    },
WebRequest(WINV24,M1)    "json": null,
WebRequest(WINV24,M1)    "origin": "class="num">200.103.class="num">20.126",
WebRequest(WINV24,M1)    "url": "https:class=class="str">"cmt">//httpbin.org/post"
WebRequest(WINV24,M1)  }
WebRequest(WINV24,M1)  
class="type">int OnInit()
  {
class=class="str">"cmt">//--- Defining variables
  class="type">class="kw">string method = "POST";                             class=class="str">"cmt">// HTTP verb in class="type">class="kw">string (GET, POST, etc...)
  class="type">class="kw">string url = "https:class=class="str">"cmt">//httpbin.org/post";            // Destination URL

◍ 把 JSON 塞进 WebRequest 的最小可用片段

在 MT5 里向外发 POST 请求,核心是先备好头、超时、收发缓冲区和返回头四个变量。下面这段直接放进 OnInit 就能跑,不依赖任何外部库。 超时设 5000 毫秒是比较务实的阈值:外汇或贵金属行情跳动时,EA 若卡在外部请求上超过 5 秒,可能错过入场或止损窗口。 请求体用 StringToCharArray 转成 char 数组,编码指定 CP_UTF8,否则中文或特殊符号容易乱码。WebRequest 返回的 status_code 为 200 表示服务端正常收下数据。 实跑日志里能看到回显:data 字段原样带回 {"key1":"value1","key2":"value2"}\u0000,末尾的 \u0000 是 char 数组自带的结束符,解析 JSON 时记得忽略。Content-Length 被自动算成 34,说明 MT5 按字节数而非字符数计长。

MQL5 / C++
  class="type">class="kw">string method = "POST";                      class=class="str">"cmt">// HTTP verb in class="type">class="kw">string (GET, POST, etc...)
  class="type">class="kw">string headers = "Content-Type: application/json";class=class="str">"cmt">// Request header
  class="type">int timeout = class="num">5000;                              class=class="str">"cmt">// Maximum waiting time class="num">5 seconds
  class="type">char data[];                                     class=class="str">"cmt">// Data we will send(body) array of type class="type">char
  class="type">char result[];                                   class=class="str">"cmt">// Data received as an array of type class="type">char
  class="type">class="kw">string result_headers;                           class=class="str">"cmt">// String with response headers
class=class="str">"cmt">//--- Treating body
  class="type">class="kw">string body = "{\"key1\":\"value1\",\"key2\":\"value2\"}";
  StringToCharArray(body,data,class="num">0,WHOLE_ARRAY,CP_UTF8);
class=class="str">"cmt">//--- Calling the function and getting the status_code
  class="type">int status_code = WebRequest(method,url,headers,timeout,data,result,result_headers);

class=class="str">"cmt">//--- Print the data
  Print("Status code: ",status_code);
  Print("Response: ",CharArrayToString(result)); class=class="str">"cmt">// We use CharArrayToString to display the response in class="type">class="kw">string form.

class=class="str">"cmt">//---
  class="kw">return(INIT_SUCCEEDED);
  }

用 WebRequest 把 JSON 推到外部接口

想在 MT5 里把行情或信号丢给外部服务,WebRequest 是唯一正路。下面这段把一段 JSON 体发到 httpbin 的测试地址,超时锁死 5 秒,避免脚本卡死在等待里。 先准备发送体:字符串 {"key1":"value1","key2":"value2"} 经 StringToCharArray 转成 char 数组,编码用 CP_UTF8。日志显示 Body Size 为 33,而数组 Array Size 为 34——多出的那个字节是字符串结尾的 \0,发包时它会一起带出去。 调用 WebRequest 后返回 status_code = 200,回传的 JSON 里 data 字段原样夹着那个 \u0000 终止符。这说明 MT5 的 char 数组封包不会自动截尾,对端解析时若不严苛倒无所谓,碰上较真的 API 就可能报脏数据。

MQL5 / C++
class="type">class="kw">string url = "https:class=class="str">"cmt">//httpbin.org/post";   // Destination URL
class="type">class="kw">string headers = "Content-Type: application/json";class=class="str">"cmt">// Request header
class="type">int timeout = class="num">5000;                       class=class="str">"cmt">// Maximum waiting time class="num">5 seconds
class="type">char data[];                              class=class="str">"cmt">// Data we will send(body) array of type class="type">char
class="type">char result[];                            class=class="str">"cmt">// Data received as an array of type class="type">char
class="type">class="kw">string result_headers;                    class=class="str">"cmt">// String with response headers
class=class="str">"cmt">//--- Tratando body
class="type">class="kw">string body = "{"key1":"value1","key2":"value2"}";
StringToCharArray(body,data,class="num">0,WHOLE_ARRAY,CP_UTF8);
Print("Body: ",body);
Print("Body Size: ",StringLen(body));
ArrayPrint(data);
Print("Array Size: ",ArraySize(data));
class=class="str">"cmt">//--- Calling the function and getting the status_code
class="type">int status_code = WebRequest(method,url,headers,timeout,data,result,result_headers);

class=class="str">"cmt">//--- Print the data
Print("Status code: ",status_code);
Print("Response: ",CharArrayToString(result)); class=class="str">"cmt">// We use CharArrayToString to display the response in class="type">class="kw">string form.

class=class="str">"cmt">//---
class="kw">return(INIT_SUCCEEDED);
}
逐行看关键点:第 1–2 行定目标 URL 和 Content-Type 头;第 3 行 timeout=5000 是硬上限;第 4–6 行声明发送体、接收体、响应头三个容器。body 赋值后 StringToCharArray 带 CP_UTF8 转码,Print 打出 Body Size: 33,ArrayPrint 露出末尾的 0(即 \0),Array Size: 34 证实终止符入数组。WebRequest 那行拿 status_code,最后 CharArrayToString 把 result 还原成可读回包。 实跑日志里 status_code 200、回包 data 字段带着 \u0000,验证了我们上面说的封包行为。开 MT5 新建脚本粘这段代码,把 url 换成你自己的接收端,就能把任何字符串载荷推出去——外汇与贵金属接口调用同样高风险,先在小资金或模拟环境验通再接实盘信号。

MQL5 / C++
class="type">class="kw">string url = "https:class=class="str">"cmt">//httpbin.org/post";   // Destination URL
class="type">class="kw">string headers = "Content-Type: application/json";class=class="str">"cmt">// Request header
class="type">int timeout = class="num">5000;                       class=class="str">"cmt">// Maximum waiting time class="num">5 seconds
class="type">char data[];                              class=class="str">"cmt">// Data we will send(body) array of type class="type">char
class="type">char result[];                            class=class="str">"cmt">// Data received as an array of type class="type">char
class="type">class="kw">string result_headers;                    class=class="str">"cmt">// String with response headers
class=class="str">"cmt">//--- Tratando body
class="type">class="kw">string body = "{"key1":"value1","key2":"value2"}";
StringToCharArray(body,data,class="num">0,WHOLE_ARRAY,CP_UTF8);
Print("Body: ",body);
Print("Body Size: ",StringLen(body));
ArrayPrint(data);
Print("Array Size: ",ArraySize(data));
class=class="str">"cmt">//--- Calling the function and getting the status_code
class="type">int status_code = WebRequest(method,url,headers,timeout,data,result,result_headers);

class=class="str">"cmt">//--- Print the data
Print("Status code: ",status_code);
Print("Response: ",CharArrayToString(result)); class=class="str">"cmt">// We use CharArrayToString to display the response in class="type">class="kw">string form.

class=class="str">"cmt">//---
class="kw">return(INIT_SUCCEEDED);
}
把通信诊断交给小布盯盘
这些请求头校验、响应异常的特征小布盯盘的AIGC已内置,打开对应品种页即可看到,你只需判断要不要调整EA逻辑。

常见问题

平台要求先在设置里把目标域名加入允许列表,且函数运行于独立线程,未配置时调用会直接失败,这是安全沙箱限制而非代码 bug。
大概率Content-Type没设成application/json,或MQL5侧字符串未转义引号,导致远端解析失败,需要在本地先序列化再发。
可以,小布盯盘的品种页会把接口异常、超时和状态码异动标出来,省去你自己在日志里翻错误码。
它封装了header模板、超时重试和错误映射,开发者只传业务参数,不用每次手写底层HTTP细节。
MQL5字符串和结构体有栈限制,大响应建议分块读取或交由Connexus缓冲,避免单次拷贝撑爆脚本内存。