如何使用 MQL4 在 WebRequest() 调用中发送带有 JSON 的 POST?
How to send a POST with a JSON in a WebRequest() call using MQL4?
我想从 MQL4
-脚本发送 POST
,使用 JSON-格式到节点服务器。
我已经根据以下文档在 MQL4
中尝试了 webRequest()
标准函数,但没有成功。
From MQL4 Documentation:
Sending simple requests of type "key=value" using the header `Content-Type: application/x-www-form-urlencoded`.
int WebRequest( const string method, // HTTP method
const string url, // URL
const string cookie, // cookie
const string referer, // referer
int timeout, // timeout
const char &data[], // the array of the HTTP message body
int data_size, // data[] array size in bytes
char &result[], // an array containing server response data
string &result_headers // headers of server response
);
和
Sending a request of any type specifying the custom set of headers for a more flexible interaction with various Web services.
int WebRequest( const string method, // HTTP method
const string url, // URL
const string headers, // headers
int timeout, // timeout
const char &data[], // the array of the HTTP message body
char &result[], // an array containing server response data
string &result_headers // headers of server response
);
Parameters
method [in] HTTP method.
url [in] URL.
headers [in] Request headers of type "key: value", separated by a line break "\r\n".
cookie [in] Cookie value.
referer [in] Value of the Referer header of the HTTP request.
timeout [in] Timeout in milliseconds.
data[] [in] Data array of the HTTP message body.
data_size [in] Size of the data[] array.
result[] [out] An array containing server response data.
result_headers [out] Server response headers.
Returned value:
HTTP server response code or -1 for an error.
有谁知道怎么实现吗?
更新:
这是 MQL4
脚本端的代码:
#include <Json\hash.mqh>
#include <Json\KoulJSONMgmt.mqh>
void OnStart()
{
string strParam = StringConcatenate("{","\"currency\"",":","\"",Symbol(),"\"",",","\"timeframe\"",":","\"",IntegerToString(Period()),"\"",",","\"ticktime\"",":","\"",TimeToString(TimeLocal(),TIME_DATE|TIME_SECONDS),"\"",",","\"bid\"",":",DoubleToString(MarketInfo(Symbol(),MODE_BID),4),",","\"ask\"",":",DoubleToString(MarketInfo(Symbol(),MODE_ASK),4),",","\"spread\"",":",DoubleToString(MarketInfo(Symbol(),MODE_SPREAD),0),"}");
JSONParser *parser = new JSONParser();
JSONValue *jv = parser.parse(strParam);
string strJson = jv.toString();
if (jv == NULL) {
Print("error:"+(string)parser.getErrorCode()+parser.getErrorMessage());
} else {
Print("PARSED:"+strJson);
//Example of json String :
//EURUSD,M15: PARSED:{"bid" : 1.1152,"ask" : 1.1154,"spread" : 13,"ticktime" : "2016.10.10 16:24:01","currency" : "EURUSD","timeframe" : "15"}
}
string cookie=NULL,headers;
char post[],result[];
int res;
string strResult,result_header;
headers = "application/json";
prmUrl=StringConcatenate("http://localhost/api"+"/"+"ticks");
//--- Reset the last error code
ResetLastError();
int timeout=1000; //--- Timeout below 1000 (1 sec.) is not enough for slow Internet connection
int intHostNameLength=StringLen(prmParameter);
StringToCharArray(prmParameter,post,0,intHostNameLength);
res=WebRequest("POST",prmUrl,headers,timeout,post,result,result_header);
//--- Checking errors
if(res==-1)
{
Print("Error in WebRequest. Error code =",GetLastError());
//--- Perhaps the URL is not listed, display a message about the necessity to add the address
Print("Add the address '"+prmUrl+"' in the list of allowed URLs on tab 'Expert Advisors'","Error",MB_ICONINFORMATION);
}
else
{
for(int i=0;i<ArraySize(result);i++)
{
if( (result[i] == 10) || (result[i] == 13)) {
continue;
} else {
strResult += CharToStr(result[i]);
}
}
ArrayCopy(strResult,result,0,0,WHOLE_ARRAY);
}
Print(strResult);
}
节点端是:
server.js
//Create new Tick
app.post('/api/ticks', function(req, res) {
console.log('Inserting New Tick');
var tick = req.body;
console.log('>'+JSON.stringify(tick,null,4));
Tick.addTick(tick, function(err, tick){
if(err) res.json(err);
res.json(tick);
});
});
并在模型中 ticks.js
var mongoose = require('mongoose');
// User Schema
var TickSchema = mongoose.Schema({
currency:{
type: String
},
timeframe: {
type: String
},
ticktime: {
type: Date
},
bid: {
type: Number
},
ask: {
type: Number
},
spread: {
type: Number
},
createddate :{
type: Date,
default: Date.now
}
}, {collection : 'fxTicks'});
var Tick = module.exports = mongoose.model('Tick', TickSchema);
//Create New Tick
module.exports.addTick = function(tick, callback){
Tick.create(tick, callback);
};
// Get Ticks
module.exports.getTicks = function(callback, limit){
Tick.find(callback).limit(limit);
};
允许您的 [MetaTrader Terminal 4 ] 通过菜单与 URL 通信:
工具 -> 选项 -> 专家顾问 ->
1.在'Allow WebReq....'
前面标记一个复选框[ X ]
&
2。在复选框下方输入 URL 名称,使用绿色 (+)
图标,在里面表格。
如果这没有帮助 - 尝试添加 Print()
语句 以查看可能的错误(不正确的 MQL4
代码或不正确的 JSON-格式文件).
那么,回到一号广场:
在 last-year's post 中,有一个循序渐进的方法来进行基于 MCVE 的问题隔离方法。
在这里重复同样的步骤,在MQL4
-code,
里面
添加一个基于 python
的模型 WebSERVER,以诊断实际工作的 client/server http 协议交换和握手,( 不是 WebSERVER 端 解释 传递的 POST 请求,这与从 WebBROWSER 启动 URL 相同,因为所有相关细节参考:BaseHTTPServer.BaseHTTPRequestHandler
)
>>> import BaseHTTPServer
>>> server_class = BaseHTTPServer.HTTPServer
>>> handler_class = BaseHTTPServer.BaseHTTPRequestHandler
>>> httpd = server_class( ( '', 8765 ), handler_class )
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 09:46:45] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 09:46:45] "GET /?test=123_from_Chrome HTTP/1.1" 501 -
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 09:47:23] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 09:47:23] "GET /favicon.ico HTTP/1.1" 501 -
>>>
>>>
>>>
>>> httpd = server_class( ( '', 80 ), handler_class )
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 10:22:05] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 10:22:05] "GET /?test=123_from_Chrome_on_port_80 HTTP/1.1" 501 -
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 10:22:31] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 10:22:31] "GET /?test=123_from_Chrome_on_port_80_again HTTP/1.1" 501 -
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 10:22:34] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 10:22:34] "GET /favicon.ico HTTP/1.1" 501 -
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 11:25:56] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 11:26:12] "GET /?test=123_from_Chrome_on_port_80_another_call HTTP/1.1" 501 -
>>>
>>>
127.0.0.1 - - [10/Oct/2016 12:03:03] code 501, message Unsupported method ('POST')
127.0.0.1 - - [10/Oct/2016 12:03:03] "POST / HTTP/1.1" 501 -
>>>
输出
提供证据表明最后一对行是由 MQL4
端 WebRequest()
生成的并且设置正确且工作正常来回
[MetaTrader Terminal 4 ]-日志显示:
2016.10.10 12:03:03.921 ___Whosebug_WebRequest_DEMO XAUUSD,H1:
DATA:: <head><title>Error response</title></head>
<body>
<h1>Error response</h1><p>Error code 501.<p>
Message: Unsupported method ('POST').<p>
Error code explanation: 501 = Server does not support this operation.
</body>
2016.10.10 12:03:03.921 ___Whosebug_WebRequest_DEMO XAUUSD,H1:
HDRs:: HTTP/1.0 501 Unsupported method ('POST')
Server: BaseHTTP/0.3 Python/2.7.6
Date: Mon, 10 Oct 2016 20:03:03 GMT
Content-Type: text/html
Connection: close
一个原始的 MQL4
-snippet 但使用风险自负!
(强烈建议不要在任何生产级代码中使用任何 BLOCKING WebRequest()
调用
... and 或阅读有关分布式的高性能、低延迟、非阻塞集成工具的内部细节异构系统处理类似 ZeroMQ 或 nanomsg )
所有人都被警告了,所以:
去年的设置图仍然有效:
模型 WebSERVER 在虚线表单域输入中包含:
http://localhost/
还应记住,尝试在 URL 中设置特定端口指定将违反 MetaQuotes Inc. 设计规则,即端口是从开头的协议 pragma 派生的URL 声明,所以:
http://localhost:8765/
将不起作用,因为 MQL4 WebRequest()
不能 使用其他端口,但 { 80 | 443 }
中的任何一个,由URL 中声明的协议编译指示:{ http: | https: }
因此,对于任何端口编号操作,都必须设置和调整一组适当的端口转发服务,这将使 MetaTrader Terminal 4 留在这个设计笼中,仅使用 { 80 | 443 }
.
最简单的 MQL4
-script OnStart()
演示程序看起来像这样:
//+------------------------------------------------------------------+
//| ___Whosebug_WebRequest_DEMO.mq4 |
//| Copyright © 1987-2016 [MS] |
//| nowhere.no |
//+------------------------------------------------------------------+ >>>
#property copyright "Copyright © 1987-2016 [MS]"
#property link "nowhere.no"
#property version "1.00"
#property strict
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart(){
/* A BRIGHTER WAY:
string JSON_string = StringFormat( "{\"currency\": \"%s\", \"timeframe\": \"%d\", \"ticktime\": \"%s\", \"bid\": %f, \"ask\": %f, \"spread\": %s }", _Symbol,
Period(),
TimeToString( TimeLocal(), TIME_DATE | TIME_SECONDS ),
MarketInfo( _Symbol, MODE_BID ),
MarketInfo( _Symbol, MODE_ASK ),
MarketInfo( _Symbol, MODE_SPREAD )
);
// A SMARTER WAY & THE FASTEST PROCESSING TIMES:
// --------------
#define MQL4_COMPILE_TIME_JSON_TEMPLATE "{\"currency\": \"%s\", \"timeframe\": \"%d\", \"ticktime\": \"%s\", \"bid\": %f, \"ask\": %f, \"spread\": %s }" // CONSTANT TEMPLATE TO FILL-IN AD-HOC VALUES:
// +
string JSON_string = StringFormat( MQL4_COMPILE_TIME_JSON_TEMPLATE", _Symbol,
Period(),
TimeToString( TimeLocal(), TIME_DATE | TIME_SECONDS ),
MarketInfo( _Symbol, MODE_BID ),
MarketInfo( _Symbol, MODE_ASK ),
MarketInfo( _Symbol, MODE_SPREAD )
);
*/
string JSON_string = StringConcatenate( "{", // **** MQL4 can concat max 63 items
"\"currency\"",
":",
"\"",
Symbol(),
"\"",
",",
"\"timeframe\"",
":",
"\"",
IntegerToString( Period() ),
"\"",
",",
"\"ticktime\"",
":",
"\"",
TimeToString( TimeLocal(), TIME_DATE | TIME_SECONDS ),
"\"",
",",
"\"bid\"",
":",
DoubleToString( MarketInfo( Symbol(), MODE_BID ), 4 ),
",",
"\"ask\"",
":",
DoubleToString( MarketInfo( Symbol(), MODE_ASK ), 4 ),
",",
"\"spread\"",
":",
DoubleToString( MarketInfo( Symbol(), MODE_SPREAD ), 0 ),
"}"
);
// */
/* off-topic: a JSON-string VALIDATOR -----------------------------------------------------------------------------------------------------------------------------------
#include <Json\hash.mqh>
#include <Json\KoulJSONMgmt.mqh>
JSONParser *parser = new JSONParser();
JSONValue *jv = parser.parse(strParam);
string strJson = jv.toString();
if ( jv == NULL ) Print( "ERROR:" + (string) parser.getErrorCode()
+ parser.getErrorMessage()
);
else Print( "PARSED:" + strJson );
// Example of a journalled Print() for an above setup JSON String :
// EURUSD,M15: PARSED:{"bid" : 1.1152,"ask" : 1.1154,"spread" : 13,"ticktime" : "2016.10.10 16:24:01","currency" : "EURUSD","timeframe" : "15"}
*/ // off-topic: a JSON-string VALIDATOR -----------------------------------------------------------------------------------------------------------------------------------
// string ReqSERVER_URL = "http://localhost:8765/", // **** MQL4 WebRequest CANNOT use other port but either of { 80 | 443 } given by protocol pragma stated in URL: { http: | https: }
string ReqSERVER_URL = "http://localhost/", // ---- MQL4 WebRequst
ReqCOOKIE = NULL,
// ReqHEADERs = "application/json"; // **** MQL4 WebRequest MUST use [in] Request headers of type "key: value", separated by a line break "\r\n".
ReqHEADERs = "Content-Type: application/json\r\n";
int ReqTIMEOUT = 5000; // ---- MQL4 WebRequest SHALL use [in] Timeouts below 1000 (1 sec.) are not enough for slow Internet connection;
// ================================================= // ~~~~ MQL4 WebRequest SHALL be AVOIDED as an un-control-able BLOCKING-SHOW-STOPPER, any professional need shall use NON-BLOCKING tools
char POSTed_DATA[],
result_RECVed_DATA_FromSERVER[];
int result_RetCODE;
string result_DecodedFromSERVER,
result_RECVed_HDRs_FromSERVER;
// int intHostNameLength = StringLen( ReqSERVER_URL );
// StringToCharArray( ReqSERVER_URL, POSTed_DATA, 0, StringLen( ReqSERVER_URL ) );
// StringToCharArray( prmParameter, post, 0, intHostNameLength );
StringToCharArray( JSON_string, POSTed_DATA, 0, StringLen( JSON_string ) );
ResetLastError();
result_RetCODE = WebRequest( "POST",
ReqSERVER_URL,
ReqHEADERs,
ReqTIMEOUT,
POSTed_DATA,
result_RECVed_DATA_FromSERVER,
result_RECVed_HDRs_FromSERVER
);
if ( result_RetCODE == -1 ) Print( "Error in WebRequest. Error code =", GetLastError() ); // returns error 4060 – "Function is not allowed for call" unless permitted -- ref. Picture in >>>
else {
for ( int i = 0; i < ArraySize( result_RECVed_DATA_FromSERVER ); i++ ) {
if ( ( result_RECVed_DATA_FromSERVER[i] == 10 ) // == '\n' // <LF>
|| ( result_RECVed_DATA_FromSERVER[i] == 13 ) // == '\r' // <CR>
)
continue;
else result_DecodedFromSERVER += CharToStr( result_RECVed_DATA_FromSERVER[i] );
}
Print( "DATA:: ", result_DecodedFromSERVER );
Print( "HDRs:: ", result_RECVed_HDRs_FromSERVER );
}
}
//+------------------------------------------------------------------+
Deviations from documented steps are easily visible in the source and were left for clarity.
结语:
如果文档有说明,则值得保留该建议(通过一些测试,当然)。
如果赞助的社区建议说了些什么,那么在要求更多之前至少尝试一下是值得的。
您是否尝试过这样设置 headers:
headers = "Content-Type: application/json\r\n";
?
对我来说效果很好,我有这样的人:
string response = SendResquest("POST", "GetPrediction", "[4, 7]", "Content-Type: application/json", 5000);
string SendResquest(string httpType, string methodName, string bodyData = "", string headers = "", int timeout)
{
uchar bodyDataCharArray[];
ArrayResize(bodyDataCharArray, StringToCharArray(bodyData, bodyDataCharArray)-1);
int response = WebRequest(httpType, this.address+methodName, headers, timeout, bodyDataCharArray, this.resultDataCharArray, this.resultHeader);
string result = CharArrayToString(this.resultDataCharArray);
if(response == 200)
return result;
Print("Error when trying to call API : ", response);
return "";
}
我想从 MQL4
-脚本发送 POST
,使用 JSON-格式到节点服务器。
我已经根据以下文档在 MQL4
中尝试了 webRequest()
标准函数,但没有成功。
From MQL4 Documentation:
Sending simple requests of type "key=value" using the header `Content-Type: application/x-www-form-urlencoded`.
int WebRequest( const string method, // HTTP method
const string url, // URL
const string cookie, // cookie
const string referer, // referer
int timeout, // timeout
const char &data[], // the array of the HTTP message body
int data_size, // data[] array size in bytes
char &result[], // an array containing server response data
string &result_headers // headers of server response
);
和
Sending a request of any type specifying the custom set of headers for a more flexible interaction with various Web services.
int WebRequest( const string method, // HTTP method
const string url, // URL
const string headers, // headers
int timeout, // timeout
const char &data[], // the array of the HTTP message body
char &result[], // an array containing server response data
string &result_headers // headers of server response
);
Parameters
method [in] HTTP method.
url [in] URL.
headers [in] Request headers of type "key: value", separated by a line break "\r\n".
cookie [in] Cookie value.
referer [in] Value of the Referer header of the HTTP request.
timeout [in] Timeout in milliseconds.
data[] [in] Data array of the HTTP message body.
data_size [in] Size of the data[] array.
result[] [out] An array containing server response data.
result_headers [out] Server response headers.
Returned value:
HTTP server response code or -1 for an error.
有谁知道怎么实现吗?
更新:
这是 MQL4
脚本端的代码:
#include <Json\hash.mqh>
#include <Json\KoulJSONMgmt.mqh>
void OnStart()
{
string strParam = StringConcatenate("{","\"currency\"",":","\"",Symbol(),"\"",",","\"timeframe\"",":","\"",IntegerToString(Period()),"\"",",","\"ticktime\"",":","\"",TimeToString(TimeLocal(),TIME_DATE|TIME_SECONDS),"\"",",","\"bid\"",":",DoubleToString(MarketInfo(Symbol(),MODE_BID),4),",","\"ask\"",":",DoubleToString(MarketInfo(Symbol(),MODE_ASK),4),",","\"spread\"",":",DoubleToString(MarketInfo(Symbol(),MODE_SPREAD),0),"}");
JSONParser *parser = new JSONParser();
JSONValue *jv = parser.parse(strParam);
string strJson = jv.toString();
if (jv == NULL) {
Print("error:"+(string)parser.getErrorCode()+parser.getErrorMessage());
} else {
Print("PARSED:"+strJson);
//Example of json String :
//EURUSD,M15: PARSED:{"bid" : 1.1152,"ask" : 1.1154,"spread" : 13,"ticktime" : "2016.10.10 16:24:01","currency" : "EURUSD","timeframe" : "15"}
}
string cookie=NULL,headers;
char post[],result[];
int res;
string strResult,result_header;
headers = "application/json";
prmUrl=StringConcatenate("http://localhost/api"+"/"+"ticks");
//--- Reset the last error code
ResetLastError();
int timeout=1000; //--- Timeout below 1000 (1 sec.) is not enough for slow Internet connection
int intHostNameLength=StringLen(prmParameter);
StringToCharArray(prmParameter,post,0,intHostNameLength);
res=WebRequest("POST",prmUrl,headers,timeout,post,result,result_header);
//--- Checking errors
if(res==-1)
{
Print("Error in WebRequest. Error code =",GetLastError());
//--- Perhaps the URL is not listed, display a message about the necessity to add the address
Print("Add the address '"+prmUrl+"' in the list of allowed URLs on tab 'Expert Advisors'","Error",MB_ICONINFORMATION);
}
else
{
for(int i=0;i<ArraySize(result);i++)
{
if( (result[i] == 10) || (result[i] == 13)) {
continue;
} else {
strResult += CharToStr(result[i]);
}
}
ArrayCopy(strResult,result,0,0,WHOLE_ARRAY);
}
Print(strResult);
}
节点端是:
server.js
//Create new Tick
app.post('/api/ticks', function(req, res) {
console.log('Inserting New Tick');
var tick = req.body;
console.log('>'+JSON.stringify(tick,null,4));
Tick.addTick(tick, function(err, tick){
if(err) res.json(err);
res.json(tick);
});
});
并在模型中 ticks.js
var mongoose = require('mongoose');
// User Schema
var TickSchema = mongoose.Schema({
currency:{
type: String
},
timeframe: {
type: String
},
ticktime: {
type: Date
},
bid: {
type: Number
},
ask: {
type: Number
},
spread: {
type: Number
},
createddate :{
type: Date,
default: Date.now
}
}, {collection : 'fxTicks'});
var Tick = module.exports = mongoose.model('Tick', TickSchema);
//Create New Tick
module.exports.addTick = function(tick, callback){
Tick.create(tick, callback);
};
// Get Ticks
module.exports.getTicks = function(callback, limit){
Tick.find(callback).limit(limit);
};
允许您的 [MetaTrader Terminal 4 ] 通过菜单与 URL 通信:
工具 -> 选项 -> 专家顾问 ->
1.在'Allow WebReq....'
前面标记一个复选框[ X ]
&
2。在复选框下方输入 URL 名称,使用绿色 (+)
图标,在里面表格。
如果这没有帮助 - 尝试添加 Print()
语句 以查看可能的错误(不正确的 MQL4
代码或不正确的 JSON-格式文件).
那么,回到一号广场:
在 last-year's post 中,有一个循序渐进的方法来进行基于 MCVE 的问题隔离方法。
在这里重复同样的步骤,在MQL4
-code,
里面
添加一个基于 python
的模型 WebSERVER,以诊断实际工作的 client/server http 协议交换和握手,( 不是 WebSERVER 端 解释 传递的 POST 请求,这与从 WebBROWSER 启动 URL 相同,因为所有相关细节参考:BaseHTTPServer.BaseHTTPRequestHandler
)
>>> import BaseHTTPServer
>>> server_class = BaseHTTPServer.HTTPServer
>>> handler_class = BaseHTTPServer.BaseHTTPRequestHandler
>>> httpd = server_class( ( '', 8765 ), handler_class )
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 09:46:45] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 09:46:45] "GET /?test=123_from_Chrome HTTP/1.1" 501 -
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 09:47:23] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 09:47:23] "GET /favicon.ico HTTP/1.1" 501 -
>>>
>>>
>>>
>>> httpd = server_class( ( '', 80 ), handler_class )
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 10:22:05] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 10:22:05] "GET /?test=123_from_Chrome_on_port_80 HTTP/1.1" 501 -
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 10:22:31] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 10:22:31] "GET /?test=123_from_Chrome_on_port_80_again HTTP/1.1" 501 -
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 10:22:34] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 10:22:34] "GET /favicon.ico HTTP/1.1" 501 -
>>> httpd.handle_request()
127.0.0.1 - - [10/Oct/2016 11:25:56] code 501, message Unsupported method ('GET')
127.0.0.1 - - [10/Oct/2016 11:26:12] "GET /?test=123_from_Chrome_on_port_80_another_call HTTP/1.1" 501 -
>>>
>>>
127.0.0.1 - - [10/Oct/2016 12:03:03] code 501, message Unsupported method ('POST')
127.0.0.1 - - [10/Oct/2016 12:03:03] "POST / HTTP/1.1" 501 -
>>>
输出
提供证据表明最后一对行是由 MQL4
端 WebRequest()
生成的并且设置正确且工作正常来回
[MetaTrader Terminal 4 ]-日志显示:
2016.10.10 12:03:03.921 ___Whosebug_WebRequest_DEMO XAUUSD,H1:
DATA:: <head><title>Error response</title></head>
<body>
<h1>Error response</h1><p>Error code 501.<p>
Message: Unsupported method ('POST').<p>
Error code explanation: 501 = Server does not support this operation.
</body>
2016.10.10 12:03:03.921 ___Whosebug_WebRequest_DEMO XAUUSD,H1:
HDRs:: HTTP/1.0 501 Unsupported method ('POST')
Server: BaseHTTP/0.3 Python/2.7.6
Date: Mon, 10 Oct 2016 20:03:03 GMT
Content-Type: text/html
Connection: close
一个原始的 MQL4
-snippet 但使用风险自负!
(强烈建议不要在任何生产级代码中使用任何 BLOCKING WebRequest()
调用
... and 或阅读有关分布式的高性能、低延迟、非阻塞集成工具的内部细节异构系统处理类似 ZeroMQ 或 nanomsg )
所有人都被警告了,所以:
去年的设置图仍然有效:
模型 WebSERVER 在虚线表单域输入中包含:
http://localhost/
还应记住,尝试在 URL 中设置特定端口指定将违反 MetaQuotes Inc. 设计规则,即端口是从开头的协议 pragma 派生的URL 声明,所以:
http://localhost:8765/
将不起作用,因为 MQL4 WebRequest()
不能 使用其他端口,但 { 80 | 443 }
中的任何一个,由URL 中声明的协议编译指示:{ http: | https: }
因此,对于任何端口编号操作,都必须设置和调整一组适当的端口转发服务,这将使 MetaTrader Terminal 4 留在这个设计笼中,仅使用 { 80 | 443 }
.
最简单的 MQL4
-script OnStart()
演示程序看起来像这样:
//+------------------------------------------------------------------+
//| ___Whosebug_WebRequest_DEMO.mq4 |
//| Copyright © 1987-2016 [MS] |
//| nowhere.no |
//+------------------------------------------------------------------+ >>>
#property copyright "Copyright © 1987-2016 [MS]"
#property link "nowhere.no"
#property version "1.00"
#property strict
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart(){
/* A BRIGHTER WAY:
string JSON_string = StringFormat( "{\"currency\": \"%s\", \"timeframe\": \"%d\", \"ticktime\": \"%s\", \"bid\": %f, \"ask\": %f, \"spread\": %s }", _Symbol,
Period(),
TimeToString( TimeLocal(), TIME_DATE | TIME_SECONDS ),
MarketInfo( _Symbol, MODE_BID ),
MarketInfo( _Symbol, MODE_ASK ),
MarketInfo( _Symbol, MODE_SPREAD )
);
// A SMARTER WAY & THE FASTEST PROCESSING TIMES:
// --------------
#define MQL4_COMPILE_TIME_JSON_TEMPLATE "{\"currency\": \"%s\", \"timeframe\": \"%d\", \"ticktime\": \"%s\", \"bid\": %f, \"ask\": %f, \"spread\": %s }" // CONSTANT TEMPLATE TO FILL-IN AD-HOC VALUES:
// +
string JSON_string = StringFormat( MQL4_COMPILE_TIME_JSON_TEMPLATE", _Symbol,
Period(),
TimeToString( TimeLocal(), TIME_DATE | TIME_SECONDS ),
MarketInfo( _Symbol, MODE_BID ),
MarketInfo( _Symbol, MODE_ASK ),
MarketInfo( _Symbol, MODE_SPREAD )
);
*/
string JSON_string = StringConcatenate( "{", // **** MQL4 can concat max 63 items
"\"currency\"",
":",
"\"",
Symbol(),
"\"",
",",
"\"timeframe\"",
":",
"\"",
IntegerToString( Period() ),
"\"",
",",
"\"ticktime\"",
":",
"\"",
TimeToString( TimeLocal(), TIME_DATE | TIME_SECONDS ),
"\"",
",",
"\"bid\"",
":",
DoubleToString( MarketInfo( Symbol(), MODE_BID ), 4 ),
",",
"\"ask\"",
":",
DoubleToString( MarketInfo( Symbol(), MODE_ASK ), 4 ),
",",
"\"spread\"",
":",
DoubleToString( MarketInfo( Symbol(), MODE_SPREAD ), 0 ),
"}"
);
// */
/* off-topic: a JSON-string VALIDATOR -----------------------------------------------------------------------------------------------------------------------------------
#include <Json\hash.mqh>
#include <Json\KoulJSONMgmt.mqh>
JSONParser *parser = new JSONParser();
JSONValue *jv = parser.parse(strParam);
string strJson = jv.toString();
if ( jv == NULL ) Print( "ERROR:" + (string) parser.getErrorCode()
+ parser.getErrorMessage()
);
else Print( "PARSED:" + strJson );
// Example of a journalled Print() for an above setup JSON String :
// EURUSD,M15: PARSED:{"bid" : 1.1152,"ask" : 1.1154,"spread" : 13,"ticktime" : "2016.10.10 16:24:01","currency" : "EURUSD","timeframe" : "15"}
*/ // off-topic: a JSON-string VALIDATOR -----------------------------------------------------------------------------------------------------------------------------------
// string ReqSERVER_URL = "http://localhost:8765/", // **** MQL4 WebRequest CANNOT use other port but either of { 80 | 443 } given by protocol pragma stated in URL: { http: | https: }
string ReqSERVER_URL = "http://localhost/", // ---- MQL4 WebRequst
ReqCOOKIE = NULL,
// ReqHEADERs = "application/json"; // **** MQL4 WebRequest MUST use [in] Request headers of type "key: value", separated by a line break "\r\n".
ReqHEADERs = "Content-Type: application/json\r\n";
int ReqTIMEOUT = 5000; // ---- MQL4 WebRequest SHALL use [in] Timeouts below 1000 (1 sec.) are not enough for slow Internet connection;
// ================================================= // ~~~~ MQL4 WebRequest SHALL be AVOIDED as an un-control-able BLOCKING-SHOW-STOPPER, any professional need shall use NON-BLOCKING tools
char POSTed_DATA[],
result_RECVed_DATA_FromSERVER[];
int result_RetCODE;
string result_DecodedFromSERVER,
result_RECVed_HDRs_FromSERVER;
// int intHostNameLength = StringLen( ReqSERVER_URL );
// StringToCharArray( ReqSERVER_URL, POSTed_DATA, 0, StringLen( ReqSERVER_URL ) );
// StringToCharArray( prmParameter, post, 0, intHostNameLength );
StringToCharArray( JSON_string, POSTed_DATA, 0, StringLen( JSON_string ) );
ResetLastError();
result_RetCODE = WebRequest( "POST",
ReqSERVER_URL,
ReqHEADERs,
ReqTIMEOUT,
POSTed_DATA,
result_RECVed_DATA_FromSERVER,
result_RECVed_HDRs_FromSERVER
);
if ( result_RetCODE == -1 ) Print( "Error in WebRequest. Error code =", GetLastError() ); // returns error 4060 – "Function is not allowed for call" unless permitted -- ref. Picture in >>>
else {
for ( int i = 0; i < ArraySize( result_RECVed_DATA_FromSERVER ); i++ ) {
if ( ( result_RECVed_DATA_FromSERVER[i] == 10 ) // == '\n' // <LF>
|| ( result_RECVed_DATA_FromSERVER[i] == 13 ) // == '\r' // <CR>
)
continue;
else result_DecodedFromSERVER += CharToStr( result_RECVed_DATA_FromSERVER[i] );
}
Print( "DATA:: ", result_DecodedFromSERVER );
Print( "HDRs:: ", result_RECVed_HDRs_FromSERVER );
}
}
//+------------------------------------------------------------------+
Deviations from documented steps are easily visible in the source and were left for clarity.
结语:
如果文档有说明,则值得保留该建议(通过一些测试,当然)。
如果赞助的社区建议说了些什么,那么在要求更多之前至少尝试一下是值得的。
您是否尝试过这样设置 headers:
headers = "Content-Type: application/json\r\n";
?
对我来说效果很好,我有这样的人:
string response = SendResquest("POST", "GetPrediction", "[4, 7]", "Content-Type: application/json", 5000);
string SendResquest(string httpType, string methodName, string bodyData = "", string headers = "", int timeout)
{
uchar bodyDataCharArray[];
ArrayResize(bodyDataCharArray, StringToCharArray(bodyData, bodyDataCharArray)-1);
int response = WebRequest(httpType, this.address+methodName, headers, timeout, bodyDataCharArray, this.resultDataCharArray, this.resultHeader);
string result = CharArrayToString(this.resultDataCharArray);
if(response == 200)
return result;
Print("Error when trying to call API : ", response);
return "";
}