Versuche HTTP POST Client zu bauen
-
Hallo,
ich weis nicht genau in welches Forum ich schreiben soll, ich habe im Internet ein Tutorial gefunden in dem C++ Code vorkommt und ich schaffe es nicht alleine dieses Programm zum laufen zu bringen.
hier ist der Link vond er Seite: http://codebase.mql4.com/7353
Normalerweise soll man damit eine Datei vom PC zu einen Webserver senden koennen, ich weis aber nicht wo der Fehler ist, ob im C++ Code etwas nicht stimmt oder in meiner PHP Seite oder insgesamt verstehe ich vielleicht etwas falsch und wuerde mich freuen wenn jemand mich in die richtige Richtung lenkt.
-
Um dir helfen zu können, müssen wir mehr über deine Probleme wissen. "Geht nicht" ist keine Fehlerbeschreibung, aus der wir irgendwelche Schlüsse ziehen können. Siehe:
http://www.c-plusplus.net/forum/200753
und
http://www.tty1.net/smart-questions_de.htmlDiese Anweisungen mögen grob klingen, sind aber hilfreich gemeint. Du gehst auch nicht zum Arzt und sagst ihm nur, dass etwas mit dir nicht stimmt.
-
Danke fuer den Hinweis.
Ich schreibe hier jetzt den Code der Function auf die eine HTTP POST Verbindung machen sollte und will dan direkt fragen ob jemand beim Funktionsaufbau sehen kann ob da ein Fehler drine ist und wenn nicht kann mir villeicht jemand sagen wie die PHP Seite aufgebaut sein muss damit das funktioniert.
// // Dumb HTTP Client library for Metatrader 4 / MT4 / MQL4 - 0.1 // // Native scripting, no external dll required but standard windows wininet // with (ascii/binary) file uploads as well - by gunzip <spammmmme@gmail.com> // // USAGE EXAMPLE // // #include <ghttp.mqh> // // string params[2][2]; // params[0][0] = "key1"; // params[0][1] = "value1"; // params[1][0] = "key2"; // params[1][1] = "value2"; // // string filenames[1][2]; // filenames[0][0] = "uploaded"; // filenames[0][1] = "test.txt"; // // string response; // // HttpPOST("127.0.0.1", "/upload.php", params, filenames, response); // HttpGET("http://www.google.com?q=hello", response); // Comment(response); // // * note that you _must_ pass two arrays for params and filenames. // pass an empty two dimensional array if you have no files/params (ie. string params[][];) // // GREETS GO TO // // - http://www.desynced.net/fx/eas/mq4script-12241.php - grabweb library for mt4 // - http://codebase.mql4.com/4428 - mt4 http client by JavaDev // - http://stackoverflow.com/questions/1985345/dev-c-wininet-upload-file-using-http // - http://stackoverflow.com/questions/471198/is-there-any-good-example-of-http-upload-using-wininet-c-library // - http://source.winehq.org/source/include/wininet.h #include <stdlib.mqh> #import "wininet.dll" #define INTERNET_OPEN_TYPE_DIRECT 0 #define INTERNET_OPEN_TYPE_PRECONFIG 1 #define INTERNET_OPEN_TYPE_PROXY 3 // Had to cut the following two defines because of silly MQL4 identifier limits #define _IGNORE_REDIRECT_TO_HTTP 0x00008000 #define _IGNORE_REDIRECT_TO_HTTPS 0x00004000 #define INTERNET_FLAG_KEEP_CONNECTION 0x00400000 #define INTERNET_FLAG_NO_AUTO_REDIRECT 0x00200000 #define INTERNET_FLAG_NO_COOKIES 0x00080000 #define INTERNET_FLAG_RELOAD 0x80000000 #define INTERNET_FLAG_NO_CACHE_WRITE 0x04000000 #define INTERNET_FLAG_DONT_CACHE 0x04000000 #define INTERNET_FLAG_PRAGMA_NOCACHE 0x00000100 #define INTERNET_FLAG_NO_UI 0x00000200 #define HTTP_ADDREQ_FLAG_ADD 0x20000000 #define HTTP_ADDREQ_FLAG_REPLACE 0x80000000 #define INTERNET_SERVICE_HTTP 3 #define INTERNET_DEFAULT_HTTP_PORT 80 #define ICU_ESCAPE 0x80000000 #define ICU_USERNAME 0x40000000 #define ICU_NO_ENCODE 0x20000000 #define ICU_DECODE 0x10000000 #define ICU_NO_META 0x08000000 #define ICU_ENCODE_PERCENT 0x00001000 #define ICU_ENCODE_SPACES_ONLY 0x04000000 #define ICU_BROWSER_MODE 0x02000000 #define AGENT "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461)" #define BUFSIZ 128 #define REQUEST_FILE "_req.txt" ////////////// PROTOTYPES bool InternetCanonicalizeUrlA(string lpszUrl, string lpszBuffer, int& lpdwBufferLength[], int dwFlags); int InternetOpenA(string sAgent, int lAccessType, string sProxyName="", string sProxyBypass="", int lFlags=0); int InternetOpenUrlA(int hInternetSession, string sUrl, string sHeaders="", int lHeadersLength=0, int lFlags=0, int lContext=0); int InternetReadFile(int hFile, string sBuffer, int lNumBytesToRead, int& lNumberOfBytesRead[]); int InternetCloseHandle(int hInet); int InternetConnectA(int handle, string host, int port, string user, string pass, int service, int flags, int context); bool HttpSendRequestA(int handle, string headers, int headersLen, int& optional[], int optionalLen); bool HttpAddRequestHeadersA(int handle, string headers, int headersLen, int modifiers); int HttpOpenRequestA(int hConnect, string lpszVerb, string lpszObjectName, string lpszVersion, string lpszReferer, string& lplpszAcceptTypes[], int dwFlags, int dwContext); #import //////// CODE bool HttpGET(string strUrl, string& strWebPage) { int hSession = InternetOpenA(AGENT, INTERNET_OPEN_TYPE_DIRECT, "0", "0", 0); int hReq = InternetOpenUrlA(hSession, strUrl, "0", 0, INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD, 0); if (hReq == 0) { return(false); } int lReturn[] = {1}; string sBuffer = ""; while (TRUE) { if (InternetReadFile(hReq, sBuffer, BUFSIZ, lReturn) <= 0 || lReturn[0] == 0) { break; } strWebPage = StringConcatenate(strWebPage, StringSubstr(sBuffer, 0, lReturn[0])); } InternetCloseHandle(hReq); InternetCloseHandle(hSession); return (true); } /////////// POST bool HttpPOST(string host, string script, string params[][], string filenames[][], string& strWebPage) { int hIntrn = InternetOpenA(AGENT, INTERNET_OPEN_TYPE_DIRECT, "0", "0", 0); if (hIntrn == 0) { return (false); } int hConn = InternetConnectA(hIntrn, host, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL); if (hConn == 0) { return (false); } int dwOpenRequestFlags = // _IGNORE_REDIRECT_TO_HTTP | // _IGNORE_REDIRECT_TO_HTTPS | // INTERNET_FLAG_KEEP_CONNECTION | // INTERNET_FLAG_NO_AUTO_REDIRECT | // INTERNET_FLAG_NO_COOKIES | // INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_RELOAD; string accept[] = {"Accept: text/*\r\n"}; int hReq = HttpOpenRequestA(hConn, "POST", script, "HTTP/1.0", NULL, accept, dwOpenRequestFlags, NULL); string strBoundary = "---------------------------HOFSTADTER"; string strContentHeader = "Content-Type: multipart/form-data; boundary=" + strBoundary; HttpAddRequestHeadersA(hReq, strContentHeader, StringLen(strContentHeader), HTTP_ADDREQ_FLAG_REPLACE); int i = 0, idx = 0, r = 0, len = 0 ; string hdr = ""; int _req = FileOpen(REQUEST_FILE, FILE_BIN|FILE_WRITE); if(_req <= 0) { return (false); } // Add parameters to request body for (i = ArrayRange(params, 0) - 1; i >= 0; i--) { hdr = StringConcatenate( "--", strBoundary, "\r\n", "Content-Disposition: form-data; name=\"", params[i][0], "\"\r\n\r\n", params[i][1], "\r\n"); FileWriteString(_req, hdr, StringLen(hdr)); } // Add files to request body for (i = ArrayRange(filenames, 0) - 1; i >= 0; i--) { hdr = StringConcatenate( "--", strBoundary, "\r\n", "Content-Disposition: form-data; name=\"", filenames[i][0], "\"; filename=\"", filenames[i][1], "\"\r\n", "Content-Type: application/octet-stream\r\n\r\n"); FileWriteString(_req, hdr, StringLen(hdr)); int handle = FileOpen(filenames[i][1], FILE_BIN|FILE_READ); if(handle <= 0) { return (false); } len = FileSize(handle); for (int b = 0; b < len; b++) { FileWriteInteger(_req, FileReadInteger(handle, CHAR_VALUE), CHAR_VALUE); } FileClose(handle); } string boundaryEnd = "\r\n--" + strBoundary + "--\r\n"; FileWriteString(_req, boundaryEnd, StringLen(boundaryEnd)); FileClose(_req); // Re-reads saved POST data byte-to-byte from file in the pseudo-character array // we need to send with HttpSendRequestA. This is due to the fact I know no clean // way to cast strings _plus_ binary file contents to a character array in MQL. // If you know how to do it properly feel free to contact me. int request[]; _req = FileOpen(REQUEST_FILE, FILE_BIN|FILE_READ); if (_req <= 0) { return (false); } len = FileSize(_req); ArrayResize(request, len); ArrayInitialize(request, 0); for (i = 0; i < len; i++) { request[r] |= FileReadInteger(_req, CHAR_VALUE) << (idx * 8); idx = (idx + 1) %4; if (idx == 0) { r++; } } FileClose(_req); if (!HttpSendRequestA(hReq, NULL, 0, request, len)) { return (false); } // Read response int lReturn[] = {1}; string sBuffer = ""; while (TRUE) { if (InternetReadFile(hReq, sBuffer, BUFSIZ, lReturn) <= 0 || lReturn[0] == 0) { break; } strWebPage = StringConcatenate(strWebPage, StringSubstr(sBuffer, 0, lReturn[0])); } InternetCloseHandle(hReq); InternetCloseHandle(hConn); InternetCloseHandle(hIntrn); return (true); } string UrlEncode(string url) { string out = ""; int len = StringLen(url); for (int i = 0; i < len; i++) { int c = StringGetChar(url, i); if (_IsReservedChar(c)) { out = StringConcatenate(out, "%", StringSubstr(IntegerToHexString(c), 6, 2)); } else { out = StringConcatenate(out, StringSubstr(url, i, 1)); } } return (out); } bool _IsReservedChar(int c) { static int encode[] = { '!', '*', 0x27 /* single quote */, '(', ')', ';', ':', '@', '&', '=', '+', '$', '/', '?', '#', '[', ']' }; for (int i = ArraySize(encode) - 1; i >= 0; i--) { if (c == encode[i]) { return (true); } } return (false); }
Es geht mir jetzt um die HttpPOST() Funktion, mit der anderen HttpGET() Funktion konnte ich schon erfolgreich Webseiten aufrufen und Parameter and PHP Seiten senden. Ich weis aber im Moment nicht wie ich korrekt die HttpPOST() Funktion einsetzen muss, damit ich damit eine Datei versenden kann, wuerde mich freuen wenn jemand weiter helfen kann.
-
Ich würde noch etwas mehr #defines verwenden und auch noch mehr Kommentare wie "// Defines", "// Includes" oder "// Include Guard intentionally left out" hinschreiben. Den using namespace std; kann man auch gern nochmal hinschreiben und die return-Werte würde ich mindestens doppelt klammern.
-
hi, weist du der code ist nicht von mir, ich habe das aus der seite zu der ich den link auch oben geschrieben habe. Und ich wuerde gerne wissen wie ich das zum laufen bringen kann. Ich bin auch kein C++ Programmierer sondern kann nur die Syntax einigermassen nachlesen.
-
0x27 /* single quote */
War es für den Coder anstrengend, diese Escape-Sequenz
'\''
zu verwenden?Diese Initialisierung eines Strings ist auch recht speziell:
string sBuffer = "";
Aber abgesehen von solchen Kleinigkeiten gibt es auch Hauer. Kein RAII.
Der Code ist zwar nicht von dir, aber korrigieren kannst du ihn wiederum auch nicht?
-
ich habe den code von der seite hier: http://codebase.mql4.com/7353
der coder der das gebaut hat, hat von windows wininet verschiedene funktionen importiert.
in dem programm wo die wininet funktion hinein importiert wurden, wird mit einer sprache programmiert die MQL4 heist und die ist vom syntax aufbau ein wenig aehnlich wie C++ aber nicht gleich.
wenn sich jemand hier etwas mit den wininet funktionen auskennt, kann er vielleicht sehen ob alles korrekt ist.
und vieleicht kann mir dann jemand sagen wie ich austesten kann ob der HTTP Request korrekt gesendet wird, damit ich bei der Fehlersuche ausschliesen kann was bereits funktioniert und was noch nicht laeuft.
Der aufbau ist ja so, das vom MQL4 Program aus diese HTTPPOST Funktion aufgerufen wird und die verweist dann auf eine Internetadresse, wobei ich noch nicht mal mir so sicher bin wie ich die Parameter korrekt setzen muss, im Beispiel das der Programmierer gemacht hat, steht irgendwie etwas anderes als eine INternetadresse, hier schaut mal:
HttpPOST("127.0.0.1", "/upload.php", params, filenames, response);
-
CplusplusUser schrieb:
im Beispiel das der Programmierer gemacht hat, steht irgendwie etwas anderes als eine INternetadresse, hier schaut mal:
HttpPOST("127.0.0.1", "/upload.php", params, filenames, response);
Das ist auch eine Internetadresse, nur ist es eben localhost.
-
Ja das kenne ich localhost.
Wie kann ich den ueberpruefen ob die Funktion jetzt die richtigen Daten an eine PHP Seite sendet, falls die Funktion die PHP Seite beispielweise gar nicht erreicht mueste ja etwas an der Funktion nicht stimmen?
-
Da musst du eben auf localhost einen server aufsetzen der eine Funktion upload.php hat.
EDIT:
Oder evtl. einfacher: Hol dir einen kostenlosen account z.B. bei funpic.de und lade da upload.php hoch.
-
Ich habe so ein kostenlosen webserver, aber ich weis im moment noch nicht wie das ablaufen muss, wie muss den die upload.php Datei aussehen? Wie kann ich den testen ob die HTTPPOST Funktion die upload.php Seite erreicht? Wenn ich das schon mal wueste koennte ich Schrittweise austesten ob die HTTPPOST Funktion ueberhaupt die upload.php auf dem Webserver erreicht und wenn das klappt muss ich noch wissen was fuer Daten an sie gesendet wurden und wie ich die Daten auf den Webserver abspeicher.
-
Da fehlt dir wohl noch so einiges an grundlegendem Wissen.
Vielleicht solltest du die ganze Sache erst mal auf einem niedrigeren Level angehen.
Nichts für ungut.
-
Das Problem wird sein, dass der Code kein C++ ist. Kann man an so Dingen wie
string& lplpszAcceptTypes[]
sehen. Es handelt anscheinend sich um etwas, das sich "MetaQuotes Language 4" nennt und lose auf C++ zu basieren scheint, aber das durch einen C++-Compiler schieben zu wollen, dürfte hoffnungslos sein.
Ich lass mal einen Link auf POCO da, die haben schön einfaches HTTP-Zeug.
-
Ist das ein .... Array von Referenzen?
-
Referenz auf ein Array, wie's aussieht. Wie gesagt, das ist kein C++.
-
Ich weis auch nicht genau welche Programmiersprache das ist, aber ich glaube man muss da nichts mehr kompilieren.
So wie ich das verstanden habe werden aus der bereits fertigen windows wininet.dll funktionen importiert und dann baustein kasten artig eine HTTPPOST Funktion damit gebaut.
Die HTTPGET Funktion aus diesem Code dort habe ich ja schon erfolgreich eingesetzt und die HTTPPOST Funktion funktioniert wahrscheinlich genauso irgendwie, ich verstehe im Moment wohl einfach nicht wie ich die Funktion mit Parametern richtig benutzen muss.
Bei der HTTPGET Funktion aus dem BEispiel dort ist es ja sehr einfach, dort schreibe ich einfach Parameter an die Internetadresse und in der PHP Datei kann ich die Parameter mit $_GET['Parameter'] einfach abfragen, wie das aber mit versenden einer Datei und der dort gebauten HTTPPOST Funktion funktioniert habe ich noch nicht verstanden. Ich weis weder wie die Parameter bei der HTTPPOSt Funktion richtig gesetzt werden muessen noch weis ich wie der PHP Code aussehen muss, damit das alles zusammen funktioniert.
-
CplusplusUser schrieb:
hi, weist du der code ist nicht von mir, ich habe das aus der seite zu der ich den link auch oben geschrieben habe. Und ich wuerde gerne wissen wie ich das zum laufen bringen kann. Ich bin auch kein C++ Programmierer sondern kann nur die Syntax einigermassen nachlesen.
Dann nimm wget statt sinnlos mit
C++ner komischen C++-artigen Skriptsprache die keiner kennt oder versteht rumzumachen.
Oder von mir aus eine der einfacheren Teletubby-Sprachen ala Python.
-
Das Problem ist das ich diese HTTPPOST Funktion aus der MQL Datei heraus benutzen will, weil ich ein Programm schon fertig gebaut habe mit MQL und es aber nicht schaffe die HTTPPOST Funktion richtig ein zu setzen.
-
Und aus MQL kannst du kein File auf die Platte speicher und dann wget.exe rausstarten?
BTW: zwei Programme (Client+Server) gleichzeitig debuggen, weil man net weiss wo es nun hakt, ist doof.
Guck erstmal dass der PHP Teil passt. Indem du ein fertiges Utility ala wget verwendest um den POST abzusetzen.
Und wenn das mal funktioniert, dann widme dich der Client-Seite.
-
Mit MQL kann ich Dateien auf der Platte speichern, aber was wget.exe ist muss ich erst noch nachlesen, das kenne ich noch nicht.
Eine funktionierende PHP Datei wo ein Forumular ist mit dem man eine Datei vom PC auf den Webserver speichern kann habe ich auch, aber wie das mit dieser HTTPPOST Funktion aus der MQL Datei zusammen funktionieren soll verstehe ich nicht.