SocketTlsReadAvailable

Lesen aller verfügbaren Daten einer sicheren TLS-Verbindung

int  SocketTlsReadAvailable(
   int           socket,               // Socket
   uchar&        buffer[],             // Puffer für die vom Socket gelesenen Daten
   const uint    buffer_maxlen         // Anzahl der zu lesenden Bytes
   );

Parameter

socket

[in]  Das Handle des Sockets, das von der Funktion SocketCreate erzeugt worden war. Wurde ein ungültiges Handle erstellt, wird der Fehler 5270 (ERR_NETSOCKET_INVALIDHANDLE) der Variablen _LastError zugewiesen.

buffer

[out]  Referenz eines Arrays vom Typ uchar, dem die Daten zugewiesen werden sollen. Die Größe des dynamischen Arrays wird auf die Anzahl der zu lesenden Bytes gesetzt. Die Arraygröße kann INT_MAX (2147483647) nicht überschreiten.

buffer_maxlen

[in]  Anzahl der Bytes, die dem Array buffer[] zugewiesen werden sollen. Daten, die nicht in das Array passen, verbleiben im Socket. Diese können beim nächsten Aufruf von SocketTlsReadAvailable oder SocketTlsRead abgerufen werden. buffer_maxlen darf nicht größer sein als INT_MAX (2147483647).

Rückgabewert

Bei einem Erfolg wird die Anzahl der gelesenen Bytes zurückgegeben. Im Fehlerfall wird -1 zurückgegeben.

Hinweis

Im Fehlerfall eines System-Sockets wird, beim Aufruf der Funktion, die Verbindung, die mit SocketConnect erstellt wurde, beendet.

Im Falle eines Fehlers beim Lesen wird der Fehler 5273 (ERR_NETSOCKET_IO_ERROR) der Variablen _LastError zugewiesen.

Die Funktion kann nur von Expert Advisors und Skripten aufgerufen werden, da sie in ihrem eigenen Ausführungsthread laufen. Wenn sie ein Indikator aufruft, wird von GetLastError() der Fehler 4014 – "Funktionsaufruf ist nicht erlaubt" ausgeworfen.

Beispiel:

//+------------------------------------------------------------------+
//|                                       SocketTlsReadAvailable.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com
#property version     "1.00"
#property script_show_inputs
//+------------------------------------------------------------------+
//| Script Eingaben                                                  |
//+------------------------------------------------------------------+
input string InpMethod ="GET";            // Method (HEAD,GET)
input string InpServer ="www.google.com"// Server
input uint   InpPort   =443;              // Port
input uint   InpTimeout=5000;             // Timeouts
//+------------------------------------------------------------------+
//| Skript Programm Start Funktion                                   |
//+------------------------------------------------------------------+
void OnStart(void)
  {
   Print("Server: ",InpServer);
   Print("Port: ",InpPort);
//--- Socket erstellen und sein Handle zuweisen
   const int socket=SocketCreate();
 
   if(socket==INVALID_HANDLE)
     {
      Print("SocketCreate() failed. Error ",GetLastError());
      return;
     }
//--- Festlegen der Timeouts für den Empfang und das Senden von Daten eines Socket-Systemobjekts
   if(!SocketTimeouts(socket,InpTimeout,InpTimeout))
     {
      PrintFormat("SocketTimeouts(%u, %u) failed. Error %d",InpTimeout,InpTimeout,GetLastError());
      SocketClose(socket);
      return;
     }
//--- connect to Server via Port
   if(!SocketConnect(socket,InpServer,InpPort,InpTimeout))
     {
      PrintFormat("SocketConnect('%s', %u, %u) failed. Error %d",InpServer,InpPort,InpTimeout,GetLastError());
      SocketClose(socket);
      return;
     }
//--- Daten über das zur Sicherung der Netzwerkverbindung verwendete Zertifikat abrufen
   string   subject,issuer,serial,thumbprint;
   datetime expiration;
 
   if(SocketTlsCertificate(socket,subject,issuer,serial,thumbprint,expiration))
     {
      Print("TLS certificate:");
      Print("   Owner:      ",subject);
      Print("   Issuer:     ",issuer);
      Print("   Number:     ",serial);
      Print("   Print:      ",thumbprint);
      Print("   Expiration: ",expiration);
     }
   else
     {
      //--- der Server stellt kein Zertifikat bereit - eine ungesicherte Verbindung melden und verlassen
      Print("The connection is not secured by a certificate");
      SocketClose(socket);
      return;
     }
//--- Senden einer Anfrage an den Server
   string request=StringFormat("%s / HTTP/1.1\r\nHost: %s\r\nUser-Agent: MetaTrader 5\r\n\r\n",InpMethod,InpServer);
 
   if(HTTPSendTLS(socket,request))
     {
      //--- Request gesendet - Response erhalten
      Print("\nRequest sent. Starting page loading...");
      uchar response[]; // alle erhaltenen Daten (Header und Haupteil des Dokuments)
 
      if(!HTTPRecvTLS(socket,response,InpTimeout))
        {
         Print("There were errors while reading the page");
         SocketClose(socket);
         return;
        }
      //--- Ausgabe der Anzahl der empfangenen Datenbytes
      PrintFormat("%u bytes received",response.Size());
      //--- Ausgabe nur des Headers der erhaltenen Seite
      string result    =CharArrayToString(response,0,WHOLE_ARRAY,CP_UTF8);
      int    header_end=StringFind(result,"\r\n\r\n");
 
      if(header_end>0)
        {
         Print("\nHTTP answer header received:");
         Print(StringSubstr(result,0,header_end));
        }
     }
//--- Schließen des Sockets nach Gebrauch
   SocketClose(socket);
   /*
   Ergebnis:
   Serverwww.google.com
   Port443
   TLS certificate:
      Owner: /CN=www.google.com
      Issuer: /C=US/O=Google Trust Services/CN=WR2
      Number0d:43:b1:4a:bb:9c:15:96:10:e1:3d:55:23:9f:25:4e
      Print89167618e5017f813aff981c88ce422dc1016bdf
      Expiration2024.12.30 08:26:35
 
   Request sentStarting page loading...
   HTTPRecvTLSDocument received within 27 attempts
   25185 bytes received
 
   HTTP answer header received:
   HTTP/1.1 200 OK
   DateFri25 Oct 2024 17:12:42 GMT
   Expires: -1
   Cache-Controlprivatemax-age=0
   Content-Typetext/htmlcharset=ISO-8859-1
   Content-Security-Policy-Report-Onlyobject-src 'none';base-uri 'self';script-src 'nonce-CUL2rdUOeAN7xIV6v0WUuQ' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inlinehttpshttp:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
   Accept-CHSec-CH-Prefers-Color-Scheme
   P3PCP="This is not a P3P policy! See g.co/p3phelp for more info."
   Servergws
   X-XSS-Protection0
   X-Frame-OptionsSAMEORIGIN
   Set-CookieAEC=AVYB7coyYMCdweTDTaWeGYzmRnxzKGqsOEosH_VkbCn8xhWkFz6v0kxQFwexpires=Wed23-Apr-2025 17:12:42 GMTpath=/; domain=.google.comSecureHttpOnlySameSite=lax
   Set-CookieNID=518=J02X02Ff4v_9sMcNoUz-1SolmuG08E26Gs438ik0J_SOJUMy7of-P-qup-LaNSWVXUL8OjhOXpGIGuJQGIoEPBnzqDKCH-46_FN4J2foHeWTlGG8bVVvQ44AHWLg1OXjrGp3CUBexYdczLWNy3LxEcb7eh6mxSvFzOelPC6-vpXkaumLQ80x9gF_RpLcAYfN4ehTexpires=Sat26-Apr-2025 17:12:42 GMTpath=/; domain=.google.comHttpOnly
   Alt-Svch3=":443"ma=2592000,h3-29=":443"ma=2592000
   Accept-Rangesnone
   VaryAccept-Encoding
   Transfer-Encodingchunked
   */
  }
//+------------------------------------------------------------------+
//| Senden einer HTTP-Anfrage über eine sichere Verbindung           |
//+------------------------------------------------------------------+
bool HTTPSendTLS(int socket,const string request)
  {
//--- Umwandeln der Zeichenkette in ein Zeichenarray mit dem Löschen der abschließenden Null
   char req[];
   int  len=StringToCharArray(request,req,0,WHOLE_ARRAY,CP_UTF8)-1;
 
   if(len<0)
      return false;
 
   return(SocketTlsSend(socket,req,len)==len);
  }
//+------------------------------------------------------------------+
//| Abrufen einer Web-Seite über eine sichere Verbindung             |
//+------------------------------------------------------------------+
bool HTTPRecvTLS(int socket,uchar &response[],const uint timeout_ms)
  {
//--- Lesen der verfügbaren Daten einer sicheren TLS-Verbindung, bevor die Zeitüberschreitung abläuft
   ulong timeout_check=GetTickCount64()+timeout_ms;
   uchar block[1024];   // Puffer für den Datenblock, gelesen vom Soket
   uint  attempt=0;     // Angeforderte Anzahl von Datenblocks
   int   err    =0;     // Fehlernummer
 
   ResetLastError();
 
   do
     {
      //--- Lesen der Blöcke, maximal 1024 Bytes
      int len=SocketTlsReadAvailable(socket,block,1024);
 
      if(len>0)
        {
         attempt++;
         //--- Zusammenführen der erhaltenen Datenblöcke
         ArrayCopy(response,block,response.Size());
         //--- Auswerten der erhaltenen Daten, Bestimmen des Headers, dem Hauptteil der Seite, das Ende oder die Fehlernummer, etc.
         //...
         //...
         //...
         timeout_check=GetTickCount64()+timeout_ms;
        }
      else
         Sleep(10);
 
      err=GetLastError();
     }
   while(!IsStopped() && GetTickCount()<timeout_check && !err);
//--- Gab es irgendwelche Fehler während des Lesens?
   if(err)
     {
      Print("Error ",err);
      return(false);
     }
 
   PrintFormat("%s: Document received within %d attempts",__FUNCTION__,attempt);
   return(true);
  }

Siehe auch

SocketTimeouts, MathSwap