SocketTlsReadAvailable

Lee todos los datos disponibles de una conexión TLS protegida.

int  SocketTlsReadAvailable(
   int           socket,               // socket
   uchar&        buffer[],             // búfer para leer los datos del socket
   const uint    buffer_maxlen         // número de bytes que deben ser leídos
   );

Parámetros

socket

[in]  Manejador del socket retornado por la función SocketCreate. Al transmitir un manejador incorrecto, en _LastError se registra el error 5270 (ERR_NETSOCKET_INVALIDHANDLE).

buffer

[out]  Enlace a la matriz de tipo uchar en la que se leerán los datos. El tamaño de la matriz dinámica aumenta en el número de bytes leídos. El tamaño de la matriz no puede superar INT_MAX (2147483647).

buffer_maxlen

[in]  Número de bytes que deben ser leídos en la matriz buffer[]. Los datos que no han cabido en la matriz se quedarán en el socket. Será posible obtenerlos con la siguiente llamada de SocketTlsReadAvailable o SocketTlsRead. El valor de buffer_maxlen no puede superar INT_MAX (2147483647).

Valor retornado

En caso de éxito, retorna el número de bytes leídos, en caso de error, retorna -1.

Observación

Si al ejecutar esta función aparece un error en el socket de sistema, la conexión establecida a través de SocketConnect será interrumpida.

Si se da un error de lectura de datos, en _LastError se registrará el error 5273 (ERR_NETSOCKET_IO_ERROR).

Solo se puede llamar la función desde los expertos y scripts, puesto que funcionan en su propio flujo de ejecución. Si se llama desde el indicador, GetLastError() retornará el error 4014 — "La función de sistema no está permitida para la llamada".

Ejemplo:

//+------------------------------------------------------------------+
//|                                       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
//+------------------------------------------------------------------+
//| Parámetros de entrada del script                                 |
//+------------------------------------------------------------------+
input string InpMethod ="GET";            // Method (HEAD,GET)
input string InpServer ="www.google.com"// Server
input uint   InpPort   =443;              // Port
input uint   InpTimeout=5000;             // Timeouts
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart(void)
  {
   Print("Server: ",InpServer);
   Print("Port: ",InpPort);
//--- creamos un socket y obtenemos su handle
   const int socket=SocketCreate();
 
   if(socket==INVALID_HANDLE)
     {
      Print("SocketCreate() failed. Error ",GetLastError());
      return;
     }
//--- establecemos los timeout para recibir y enviar datos para el objeto de sistema de socket
   if(!SocketTimeouts(socket,InpTimeout,InpTimeout))
     {
      PrintFormat("SocketTimeouts(%u, %u) failed. Error %d",InpTimeout,InpTimeout,GetLastError());
      SocketClose(socket);
      return;
     }
//--- nos conectamos al servidor Server por el puerto Port
   if(!SocketConnect(socket,InpServer,InpPort,InpTimeout))
     {
      PrintFormat("SocketConnect('%s', %u, %u) failed. Error %d",InpServer,InpPort,InpTimeout,GetLastError());
      SocketClose(socket);
      return;
     }
//--- obtenemos los datos sobre el certificado utilizado para proteger la conexión de red
   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
     {
      //--- el servidor no ofrece un certificado: informamos sobre la conexión insegura y salimos
      Print("The connection is not secured by a certificate");
      SocketClose(socket);
      return;
     }
//--- enviamos una solicitud al servidor
   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))
     {
      //--- solicitud enviada: obtenemos una respuesta
      Print("\nRequest sent. Starting page loading...");
      uchar response[]; // todos los datos recibidos (encabezado y cuerpo del documento)
 
      if(!HTTPRecvTLS(socket,response,InpTimeout))
        {
         Print("There were errors while reading the page");
         SocketClose(socket);
         return;
        }
      //--- informamos sobre el número de bytes de los datos recibidos
      PrintFormat("%u bytes received",response.Size());
      //--- imprimimos solo el encabezado de la página resultante
      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));
        }
     }
//--- cerramos el socket después de usarlo
   SocketClose(socket);
   /*
   resultado:
   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
   */
  }
//+------------------------------------------------------------------+
//| Envía una solicitud HTTP a través de una conexión  segura        |
//+------------------------------------------------------------------+
bool HTTPSendTLS(int socket,const string request)
  {
//--- convertimos la cadena en un array de caracteres, el cero final se descartará
   char req[];
   int  len=StringToCharArray(request,req,0,WHOLE_ARRAY,CP_UTF8)-1;
 
   if(len<0)
      return false;
 
   return(SocketTlsSend(socket,req,len)==len);
  }
//+------------------------------------------------------------------+
//| Recibe una página web a través de una conexión segura            |
//+------------------------------------------------------------------+
bool HTTPRecvTLS(int socket,uchar &response[],const uint timeout_ms)
  {
//--- leemos los datos disponibles de una conexión protegida por TLS antes de que expire el tiempo de espera
   ulong timeout_check=GetTickCount64()+timeout_ms;
   uchar block[1024];   // búfer de lectura de bloque de los datos del socket
   uint  attempt=0;     // número solicitado de bloques de datos
   int   err    =0;     // код ошибки
 
   ResetLastError();
 
   do
     {
      //--- leemos por bloques, un máximo de 1024 bytes
      int len=SocketTlsReadAvailable(socket,block,1024);
 
      if(len>0)
        {
         attempt++;
         //--- unimos los bloques de datos resultantes
         ArrayCopy(response,block,response.Size());
         //--- aquí analizamos los datos recibidos, determinamos el encabezado, el cuerpo de la página, la finalización o el error de carga, etc.
         //...
         //...
         //...
         timeout_check=GetTickCount64()+timeout_ms;
        }
      else
         Sleep(10);
 
      err=GetLastError();
     }
   while(!IsStopped() && GetTickCount()<timeout_check && !err);
//--- ¿hubo errores en la lectura?
   if(err)
     {
      Print("Error ",err);
      return(false);
     }
 
   PrintFormat("%s: Document received within %d attempts",__FUNCTION__,attempt);
   return(true);
  }

Mire también

SocketTimeouts, MathSwap