Im trying to set up a WebRequest in an Expert Advisory, wheras the server needs ~5-10 min to come up with the response. Even though I set the timeout to 3600 seconds, I get a “read timeout” after exactly 10 seconds.
The following code can be used to reproduce the behavior for MT5 Build 1881:
#property copyright ""
#property link ""
#property version "1.00"
int OnInit()
{
int ret;
char data[];
char result[];
string result_hdr = NULL;
printf("Request");
StringToCharArray("random post data", data);
ret = WebRequest("POST", "http://127.0.0.1/", "", 3600*1000, data, result,result_hdr);
printf("return: %d %d", ret, GetLastError());
printf("result: %s", CharArrayToString(result));
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason){}
void OnTick(){}
The output of this script will be the following:
2018.07.19 16:46:08.092 test (Adobe,H1) Request
2018.07.19 16:46:18.095 test (Adobe,H1) return: 1003 5203
2018.07.19 16:46:18.095 test (Adobe,H1) result: read timeout
To address the obvious:
Error code 5203: “HTTP request failed” Isn’t actually that helpful
-Return Code 1003: The documentary says “Return Value: HTTP server response code or -1 for an error.” Different behavior as documented. This HTTP status code does not exist and the server does not return anything (can be reproduced by using “nc -l -p 80” as a fake Webserver.)
-The timeout is triggered after exactly 10 seconds, so the timeout parameter seems to be ignored.
Are there some other timeout values I don’t know about or anything else, that could cause this behavior?
''Are there some other timeout values I don’t know about or anything else, that could cause this behavior?
Thanks in advance’’
WebRequest is a blocking call so I think the default timeout <= 10 seconds, however, no server should take longer than that to generate a response and if it does then the server logic isn’t properly implemented. Assuming this is your server, you should return a 503 (server busy) status if the business logic has not completed. Here is an example python server.
from time import sleep
from concurrent.futures import ThreadPoolExecutor
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_mql():
if hello_mql.future is None:
#simulate heavy business logic
hello_mql.future = ThreadPoolExecutor().submit(sleep, 60)
if hello_mql.future.done():
return 'Hello MQL!', 200
return 'SERVER BUSY', 503
hello_mql.future = None
If the server is not yours then you could implement your own middle-man service with python using the same logic.
import requests
from time import sleep
from concurrent.futures import ThreadPoolExecutor as Tpe
from flask import Flask
app = Flask(__name__)
def url_get():
sleep(20)
return requests.get('https://www.mql5.com')
@app.route('/')
def hello_mql():
if hello_mql.future is None:
hello_mql.future = Tpe().submit(url_get)
if hello_mql.future.done():
return (
hello_mql.future.result().text,
hello_mql.future.result().status_code
)
return "BUSY", 503
hello_mql.future = None
Unfortunately, returning a 503 would not solve my poroblem.
Is there any way to change this behaviour default timout? I can’t find any thing in the docs, in an older MT5 version the timeout was propperly processed…
A description of problem:
In fact I’m running a Python (django based) webserver/REST-api for interfacing tensorflow.
The idea is to make pair wise comparison of 300-500 stocks, resulting in up to 490k samples to be processed.
The timing behaviour is intended and acceptable for a daily call.
A certain speedup would be definetly possible, but not 60 times faster
I see two options here, first implement the following:
Client issues job, to be computed
Server executes job in an asynchronous way
Server returns some id
Client Polls until job id is done
Client Requests the final results
Or increase the timout…
I saw some references to WinHTTP in terminal64.exe, is that whats used internally for HTTP?
So maybe a call to WinHttpSetTimeouts could fix that problem?
I’m using REST because it’s a convenient way of providing an API, that’s human readable and it can also be interfaced with HTML/JS to provide a GUI and any other language. But mainly, I had a lot of code already laying around
Do you know a better way of using MQL with tensorflow?
You absolutely 100% need to avoid your EA hanging on a blocked webrequest call. This is why you need to program concurrency into your business logic. The flow should be something like:
Is there any reason for that? The EA runs in a separate thread, as far as I know, therefore waiting on any blocking call should be no problem. Both recv() and sleep() should hand the execution back to the kernel. I guess there is no Metatrader magic happening while sleeping, that does not happen with recv(). Even though if this were true, I could do the following to receive a blocking HTTP request (pseudocode):
//send HTTP request with "Connection: close"
//receive response
result = ""
while (connection_open(socket)) {
result += recv(socket); //Non blocking recv
Sleep(1000);
}
return result;
As my service desk request is stucked in the endless depth of the ticket wall for further investigation, I ended up implementing an HTTP client myself, what actually solved my problem… It is based on this nice article on WinSockets in MQL: https://www.mql5.com/ru/articles/2599 . As a positive side effect, I’m not restricted to port 80 anymore and can remove the (useless) proxy server. Here is the code if anyone comes across the same problem:
P.S. Why is there a copyright on such tutorials?! Technically I am not allowed to copy&paste anything from this article without permission. That somehow contradicts the purpose of a tutorial…