SocketTlsRead

Читает данные из защищенного TLS-соединения.

int  SocketTlsRead(
   int           socket,               // сокет
   uchar&        buffer[],             // буфер для чтения данных из сокета
   uint          buffer_maxlen         // количество байт, которые нужно прочитать
   );

Параметры

socket

[in]  Хэндл сокета, возвращаемый функцией SocketCreate. При передаче неверного хэндла в _LastError записывается ошибка 5270 (ERR_NETSOCKET_INVALIDHANDLE).

buffer

[out]  Ссылка на массив типа uchar, в который будут прочитаны данные. Размер динамического массива увеличивается на количество прочитанных байт. Размер массива не может превышать INT_MAX (2147483647).

buffer_maxlen

[in]  Количество байт, которые необходимо прочитать в массив buffer[]. Данные, которые не поместятся в массив, останутся в сокете. Их можно будет получить следующим вызовом SocketTLSRead. Значение buffer_maxlen не может превыщать INT_MAX (2147483647).

Возвращаемое значение

В случае успеха возвращает количество прочитанных байт, в случае ошибки возвращает -1.

Примечание

Если при выполнении этой функции на системном сокете произойдет ошибка, соединение, установленное через SocketConnect, будет разорвано.

Функция исполняется до тех пор, пока не получит указанное количество данных или не наступит таймаут (SocketTimeouts).

При ошибке чтения данных в _LastError записывается ошибка 5273 (ERR_NETSOCKET_IO_ERROR).

Функцию можно вызывать только из экспертов и скриптов, так как они работают в собственном потоке выполнения. При вызове из индикатора GetLastError() вернет ошибку 4014 – "Системная функция не разрешена для вызова".

Пример:

//+------------------------------------------------------------------+
//|                                                SocketExample.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright   "Copyright 2000-2024, MetaQuotes Ltd."
#property link        "https://www.mql5.com"
#property version     "1.00"
#property description "Для работы примера добавьте Address в список разрешенных в настройках терминала"
#property script_show_inputs
 
input string Address="www.mql5.com";
input int    Port   =80;
bool         ExtTLS =false;
//+------------------------------------------------------------------+
//| Отправка команды на сервер                                       |
//+------------------------------------------------------------------+
bool HTTPSend(int socket,string request)
  {
   char req[];
   int  len=StringToCharArray(request,req)-1;
   if(len<0)
      return(false);
//--- если используется защищенное TLS-соединение через порт 443
   if(ExtTLS)
      return(SocketTlsSend(socket,req,len)==len);
//--- если используется обычное TCP-соединение
   return(SocketSend(socket,req,len)==len);
  }
//+------------------------------------------------------------------+
//| Чтение ответа сервера                                            |
//+------------------------------------------------------------------+
bool HTTPRecv(int socket,uint timeout)
  {
   char   rsp[];
   string result;
   uint   timeout_check=GetTickCount()+timeout;
//--- читаем данные из сокета, пока они есть, но не дольше timeout
   do
     {
      uint len=SocketIsReadable(socket);
      if(len)
        {
         int rsp_len;
         //--- разные команды чтения в зависимости от того, защищенное соединение или нет
         if(ExtTLS)
            rsp_len=SocketTlsRead(socket,rsp,len);
         else
            rsp_len=SocketRead(socket,rsp,len,timeout);
         //--- разберем ответ
         if(rsp_len>0)
           {
            result+=CharArrayToString(rsp,0,rsp_len);
            //--- распечатаем только заголовок ответа
            int header_end=StringFind(result,"\r\n\r\n");
            if(header_end>0)
              {
               Print("Получен заголовок HTTP ответа:");
               Print(StringSubstr(result,0,header_end));
               return(true);
              }
           }
        }
     }
   while(GetTickCount()<timeout_check && !IsStopped());
   return(false);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   int socket=SocketCreate();
//--- проверим хэндл
   if(socket!=INVALID_HANDLE)
     {
      //--- если всё в порядке, подключаемся
      if(SocketConnect(socket,Address,Port,1000))
        {
         Print("Установлено подключение к ",Address,":",Port);
 
         string   subject,issuer,serial,thumbprint;
         datetime expiration;
         //--- если соединение защищено сертификатом, выведем его данные
         if(SocketTlsCertificate(socket,subject,issuer,serial,thumbprint,expiration))
           {
            Print("Сертификат TLS:");
            Print("   Владелец:  ",subject);
            Print("   Издатель:  ",issuer);
            Print("   Номер:     ",serial);
            Print("   Отпечаток: ",thumbprint);
            Print("   Истечение: ",expiration);
            ExtTLS=true;
           }
         //--- отправим на сервер запрос GET
         if(HTTPSend(socket,"GET / HTTP/1.1\r\nHost: www.mql5.com\r\nUser-Agent: MT5\r\n\r\n"))
           {
            Print("GET-запрос отправлен");
            //--- прочитаем ответ
            if(!HTTPRecv(socket,1000))
               Print("Не удалось получить ответ, ошибка ",GetLastError());
           }
         else
            Print("Не удалось отправить GET-запрос, ошибка ",GetLastError());
        }
      else
        {
         Print("Подключение к ",Address,":",Port," не удалось, ошибка ",GetLastError());
        }
      //--- закроем сокет после использования
      SocketClose(socket);
     }
   else
      Print("Не удалось создать сокет, ошибка ",GetLastError());
  }
//+------------------------------------------------------------------+

Смотри также

SocketTimeouts, MathSwap