Connexus入门(第一部分):如何使用WebRequest函数?·进阶篇
(2/3)· 为什么原生WebRequest在真实API对接中频频卡壳,以及Connexus库如何把底层通信变透明
在 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 与经纪商权限,而非盲目重试。
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 实际延迟调,而非照抄示例。
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 按字节数而非字符数计长。
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 就可能报脏数据。
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); }
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); }