SocketTlsReadAvailable

보안 TLS 연결에서 사용 가능한 모든 데이터를 읽습니다.

int  SocketTlsReadAvailable(
   int           socket,               // 소켓
   uchar&        buffer[],             // 소켓에서 데이터를 읽기 위한 버퍼
   const uint    buffer_maxlen         // 읽어들일 바이트 수
   );

매개 변수

socket

[in]  소켓 핸들이 SocketCreate 함수에 의해 반환됩니다. 잘못되 핸들이 _LastError로 전달될 시, 5270 에러(ERR_NETSOCKET_INVALIDHANDLE)가 활성화됩니다.

buffer

[out]  데이터를 읽을 수 있는 uchar 유형 배열에 대한 레퍼런스입니다. 동적 배열 크기가 읽기 바이트 수만큼 증가합니다. 배열의 크기는 INT_MAX (2147483647)을 초과할 수 없습니다.

buffer_maxlen

[in]  buffer[] 배열에 읽을 바이트 수. 배열에 맞지 않는 데이터는 소켓에 남아 있습니다. 다음 SocketTlsReadAvailable 또는 SocketTlsRead 호출로 수신 가능. buffer_maxlen는 INT_MAX (2147483647)를 초과할 수 없습니다.

반환값

성공적이면 읽기 바이트 수를 반환합니다. 오류인 경우, -1이 반환됩니다.

참고

함수 실행시 시스템 소켓에 오류가 발생하면, SocketConnect을 통해 설정된 연결이 중단됩니다.

데이터 읽기 오류가 발생시, 5273 에러(ERR_NETSOCKET_IO_ERROR)가 _LastError에 기록됩니다.

이 함수는 자체 실행 스레드에서 실행되므로 Expert Advisor 및 스크립트에서만 호출할 수 있습니다. 지표에서 호출하는 경우, GetLastError() 는 4014 에러– "호출이 허용되지 않는 함수입니다."가 반환됩니다.

예:

//+------------------------------------------------------------------+
//|                                       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 inputs                                                    |
//+------------------------------------------------------------------+
input string InpMethod ="GET";            // Method (HEAD,GET)
input string InpServer ="www.google.com"// Server
input uint   InpPort   =443;              // Port
input uint   InpTimeout=5000;             // Timeouts
//+------------------------------------------------------------------+
//| 스크립트 프로그램 시작 함수                                          |
//+------------------------------------------------------------------+
void OnStart(void)
  {
   Print("Server: ",InpServer);
   Print("Port: ",InpPort);
//--- 소켓을 생성하고 핸들을 수신
   const int socket=SocketCreate();
 
   if(socket==INVALID_HANDLE)
     {
      Print("SocketCreate() failed. Error ",GetLastError());
      return;
     }
//--- 소켓 시스템 객체와 관련한 데이터 수신 및 전송에 대한 시간 제한을 설정합니다.
   if(!SocketTimeouts(socket,InpTimeout,InpTimeout))
     {
      PrintFormat("SocketTimeouts(%u, %u) failed. Error %d",InpTimeout,InpTimeout,GetLastError());
      SocketClose(socket);
      return;
     }
//--- 포트를 통해 서버에 접속
   if(!SocketConnect(socket,InpServer,InpPort,InpTimeout))
     {
      PrintFormat("SocketConnect('%s', %u, %u) failed. Error %d",InpServer,InpPort,InpTimeout,GetLastError());
      SocketClose(socket);
      return;
     }
//--- 네트워크 연결을 보호하는 데 사용되는 인증서에서 데이터를 가져옵니다
   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
     {
      //--- 서버가 인증서를 제공하지 않습니다 - 보안되지 않은 연결을 보고하고 종료
      Print("The connection is not secured by a certificate");
      SocketClose(socket);
      return;
     }
//--- 서버에 요청을 보냅니다
   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))
     {
      //--- 요청 전송됨 - 응답 받기
      Print("\nRequest sent. Starting page loading...");
      uchar response[]; //수신된 모든 데이터(문서 헤더 및 본문)
 
      if(!HTTPRecvTLS(socket,response,InpTimeout))
        {
         Print("There were errors while reading the page");
         SocketClose(socket);
         return;
        }
      //--- 수신된 데이터 바이트 수 보고
      PrintFormat("%u bytes received",response.Size());
      //--- 획득한 페이지 헤더만 표시
      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));
        }
     }
//--- 사용 후 소켓 종료
   SocketClose(socket);
   /*
  결과:
   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
   */
  }
//+------------------------------------------------------------------+
//| 보안 연결을 통해 HTTP 요청 보내기                                    |
//+------------------------------------------------------------------+
bool HTTPSendTLS(int socket,const string request)
  {
//--- 문자열을 문자 배열로 변환하고 종료 0을 버립니다.
   char req[];
   int  len=StringToCharArray(request,req,0,WHOLE_ARRAY,CP_UTF8)-1;
 
   if(len<0)
      return false;
 
   return(SocketTlsSend(socket,req,len)==len);
  }
//+------------------------------------------------------------------+
//| 보안 연결을 통해 웹페이지 가져오기                                   |
//+------------------------------------------------------------------+
bool HTTPRecvTLS(int socket,uchar &response[],const uint timeout_ms)
  {
//--- 제한 시간이 만료되기 전에 보안 TLS 연결에서 사용 가능한 데이터를 읽습니다
   ulong timeout_check=GetTickCount64()+timeout_ms;
   uchar block[1024];   //소켓에서 읽는 블록 데이터를 위한 버퍼
   uint  attempt=0;     // 요청된 데이터 블록 수
   int   err    =0;     // 에러 코드
 
   ResetLastError();
 
   do
     {
      //--- 블록에서 일기 최대 1024 바이트
      int len=SocketTlsReadAvailable(socket,block,1024);
 
      if(len>0)
        {
         attempt++;
         //--- 획득한 데이터 블록 합치기
         ArrayCopy(response,block,response.Size());
         //--- 획득한 데이터를 분석하고 헤더, 페이지 본문, 종료 또는 로딩 오류 등을 정의
         //...
         //...
         //...
         timeout_check=GetTickCount64()+timeout_ms;
        }
      else
         Sleep(10);
 
      err=GetLastError();
     }
   while(!IsStopped() && GetTickCount()<timeout_check && !err);
//--- 읽는 동안 오류가 있었나요?
   if(err)
     {
      Print("Error ",err);
      return(false);
     }
 
   PrintFormat("%s: Document received within %d attempts",__FUNCTION__,attempt);
   return(true);
  }

참고 항목

SocketTimeouts, MathSwap