본문 바로가기
Computer Science/API

[API] WININET 정리

by KeepCoding 2021. 1. 14.

출처: https://phiru.tistory.com/50

 

 

신규 런칭을 하면서 API를 통한 로그인(웹, 런처), 빌링 서버 연동, OTP체크 등 기능을 추가해야 했다.

 

WININET을 사용해서 API연동 체크를 했는대 이와 관련해서 잘 정리된 글이 있어 퍼 옴.

 

----------------------------------------------

순서

----------------------------------------------

1. InternetOpen
2. InternetConnect
3. HttpOpenRequest
4. HttpSendRequest
5. HttpSendRequestEx
6. InternetQueryDataAvailable
7. InternetReadFile
8. InternetWriteFile
9. HttpEndRequest

예제...

----------------------------------------------

 

1. InternetOpen

----------------------------------------------

HINTERNET InternetOpen(
IN LPCSTR lpszAgent,
IN DWORD dwAccessType,
IN LPCSTR lpszProxyName,
IN LPCSTR lpszProxyBypass,
IN DWORD dwFlags
);
----------------------------------------------

기본 설명 : 인터넷 관련 DLL들을 초기화 한다. 이는 HTTP, FTP 모두 공통으로 사용.

대충 사용 방법 :

----------------------------------------------

HINTERNET hInternet;

hInternet = InternetOpen("HTTPTEST",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);

----------------------------------------------

인자 설명:

lpszAgent : application의 이름을 넣어면 된다. 깡. 아무거나 넣어라. 구분만 되면 된다.

dwAccessType : 인터넷 연결방식으로 다음과 같은 값이 있다.

INTERNET_OPEN_TYPE_DIRECT : Resolves all host names locally.

INTERNET_OPEN_TYPE_PRECONFIG : 레지스트에 세팅된 값을 그대로 사용한다.

INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY : Retrieves the proxy

or direct configuration from the registry and prevents the use of a startup

JScript or Internet Setup (INS) file.

INTERNET_OPEN_TYPE_PROXY : Passes requests to the proxy unless a proxybypass list is supplied and the name to be resolved bypasses the proxy.In this case, the function uses

lpszProxyName, lpszProxyBypass : Proxy를 사용할때만 사용한다 NULL 넣어라.

dwFlags : 인터넷 연결 속성이다. 다음 값을 같는다.

INTERNET_FLAG_ASYNC : 비동기 방식으로 연결한다.

INTERNET_FLAG_FROM_CACHE : 실제로 테트웍 요청을 하지 않고 캐시에서

INTERNET_FLAG_OFFLINE : 요청한 파일이 없으면 에러가 발생한다.

 

2. InternetConnect

----------------------------------------------

HINTERNET InternetConnect(
IN HINTERNET hInternetSession,
IN LPCSTR lpszServerName,
IN INTERNET_PORT nServerPort,
IN LPCSTR lpszUsername,
IN LPCSTR lpszPassword,
IN DWORD dwService,
IN DWORD dwFlags,
IN DWORD dwContext
);
----------------------------------------------

기본 설명 : HTTP,FTP,고퍼의 세션을 생성한다.

대충 사용 방법 :

----------------------------------------------

HINTERNET hHttpSection;

hHttpSection = InternetConnect(hInternet,

"www.naver.com" ,

0, "", "",
INTERNET_SERVICE_HTTP,
0,
0);

 

----------------------------------------------

인자 설명:

hInternetSession : InternetOpen의 리튼 값을 넣어라

lpszServerName : IP나 URL을 넣어라.

nServerPort : TCP/IP 포트

INTERNET_DEFAULT_FTP_PORT : Uses the default port for FTP servers (port 21).

INTERNET_DEFAULT_GOPHER_PORT : Uses the default port for

Gopher servers (port 70).

INTERNET_DEFAULT_HTTP_PORT : Uses the default port for HTTP servers (port 80).

INTERNET_DEFAULT_HTTPS_PORT : Uses the default port for HTTPS

servers (port 443).

INTERNET_DEFAULT_SOCKS_PORT : SOCKS firewall servers (port 1080).

INTERNET_INVALID_PORT_NUMBER : Uses the default port for the service

specified by dwService.

lpszUsername : FTP 에 사용되는 사용자 name (HTTP에서는 ""를 입력한다. NULL이 아니다.)

lpszPassword : FTP 에 사용되는 사용자 password (HTTP에서는 ""를 입력한다.

NULL이 아니다.)

dwService : 서비스의 종류

INTERNET_SERVICE_FTP

INTERNET_SERVICE_GOPHER

INTERNET_SERVICE_HTTP

dwFlags : FTP에만 사용되며 현재로서 사용할 수 있는 플래그는

INTERNET_FLAG_PASSIVE 밖에 없다.

dwContext : 비 동기 연결에 사용되는 컨텍스트 값인데 이에 관해서는 스타 이기면

다시 정리하겠다.

 

3. HttpOpenRequest

----------------------------------------------

HINTERNET HttpOpenRequest(
IN HINTERNET hHttpSession,
IN LPCSTR lpszVerb,
IN LPCSTR lpszObjectName,
IN LPCSTR lpszVersion,
IN LPCSTR lpszReferer,
IN LPCSTR FAR * lpszAcceptTypes,
IN DWORD dwFlags,
IN DWORD dwContext
);
----------------------------------------------

기본 설명 : 서버에 전달한 요구 정보를 만든다. 실제 서버에 전달되지는 않는다.

대충 사용 방법 :

----------------------------------------------

HINTERNET hReq;

hReq = HttpOpenRequest(hHttpSection, "get", "index.htm", NULL, NULL, NULL,0,0);

 

 

----------------------------------------------

인자 설명:

hHttpRequest :InternetConnect의 리튼값을 넣어라

lpszVerb : 요구 종류 GET, PUT, POST NULL이면 GET으로 동작한다.

lpszObjectName : 요구 사항으로 일반적으로 호출하고자 하는 파일 이름이다.

lpszVersion : 버젼 정보

lpszReferer : Address of a string that specifies the address (URL) of the document

from which the URL in the request (lpszObjectName) was obtained. If this

parameter is NULL, no "referrer" is specified.

lpszAcceptTypes : Address of a null-terminated array of LPCSTR pointers indicating

content types accepted by the client. If this parameter is NULL, no types

are accepted by the client. Servers interpret a lack of accept types to

indicate that the client accepts only documents of type "text/*" (that is,

only text documents, and not pictures or other binary files).

dwFlags : Internet flag values.

dwContext : Application-defined value that associates

this operation with any application data

4. HttpSendRequest

----------------------------------------------

BOOL HttpSendRequest(
IN HINTERNET hHttpRequest,
IN LPCSTR lpszHeaders,
IN DWORD dwHeadersLength,
IN LPVOID lpOptional,
DWORD dwOptionalLength
);
----------------------------------------------

기본 설명 : 만들어진 요구 사항을 서버에 보내 준다.

Header정보나 옵션 데이터를 같이 보내 줄 수 있다.

이에 대한 정보는 알아서 찾아라. 지금은 NULL로 한다.

대충 사용 방법 :

----------------------------------------------

HINTERNET hReq;

HttpSendRequest(hReq, NULL,0, NULL,0);

 

 

----------------------------------------------

인자 설명:

hHttpRequest :HttpOpenRequest의 리튼값을 넣어라

lpszHeaders : Additional headers to be appended to the request. This parameter can

be NULL if there are no additional headers to append.

dwHeadersLength : Length, in characters, of the additional headers. If this parameter is

-1L and lpszHeaders is not NULL, the function assumes that lpszHeaders is

zero-terminated (ASCIIZ), and the length is calculated

lpOptional : Address of any optional data to send immediately after the request

headers. This parameter is generally used for POST and PUT operations.

The optional data can be the resource or information being posted to the

server. This parameter can be NULL if there is no optional data to send.

dwOptionalLength : Length, in bytes, of the optional data. This parameter can be zero if

there is no optional data to send

 

5. HttpSendRequestEx

----------------------------------------------

BOOL HttpSendRequestEx(
IN HINTERNET hRequest,
IN LPINTERNET_BUFFERS lpBuffersIn,
OUT LPINTERNET_BUFFERS lpBuffersOut,
IN DWORD dwFlags,
IN DWORD dwContext
);
----------------------------------------------

기본 설명 : 원래의 HttpSendRequest 함수에는 큰 제한이 있습니다. 즉, 이 함수를 호출할 때 요청

하는 모든 데이터를 단일 버퍼에 넣어 제공해야 합니다. 이 제한 때문에 종종 불편이 따

르고, 특정 클라이언트 응용 프로그램에서 성능이 떨어지며, 메모리가 적은 클라이언트

컴퓨터에서 많은 양의 데이터를 업로드하지 못할 수도 있습니다. 반면에 새

HttpSendRequestEx 함수를 이용하면 프로그램에서 요청을 시작하고, 데이터를 가능

한 한 작은 조각으로 나누어 전송하고 모든 데이터가 전송되었을 때 요청을 끝낼 수 있습

니다. 이 함수가 작동하려면 컴퓨터에 Internet Explorer 4.0이 설치되어야 있어야 합니

다. Microsoft 다운로드 센터에서 다음 파일을 다운로드할 수 있습니다.
대충 사용 방법 :

----------------------------------------------

INTERNET_BUFFERS BufferIn;

HINTERNET hRequest

BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS );
BufferIn.Next = NULL;
BufferIn.lpcszHeader = NULL;
BufferIn.dwHeadersLength = 0;
BufferIn.dwHeadersTotal = 0;
BufferIn.lpvBuffer = NULL;
BufferIn.dwBufferLength = 0;
BufferIn.dwBufferTotal = dwPostSize;
BufferIn.dwOffsetLow = 0;
BufferIn.dwOffsetHigh = 0;

HttpSendRequestEx( hRequest, &BufferIn, NULL, 0, 0);

 

 

 

----------------------------------------------

인자 설명:

hHttpRequest :HttpOpenRequest의 리튼값을 넣어라

lpBuffersIn : Optional. Address of an INTERNET_BUFFERS structure

lpBuffersOut : Optional. Address of an INTERNET_BUFFERS structure

dwFlags:

HSR_ASYNC : Identical to WININET_API_FLAG_ASYNC.

HSR_SYNC : Identical to WININET_API_FLAG_SYNC.

HSR_USE_CONTEXT : Identical to WININET_API_FLAG_USE_CONTEXT.

HSR_INITIATE : Iterative operation (completed by HttpEndRequest).

HSR_DOWNLOAD : Download resource to file.

HSR_CHUNKED : Send chunked data.

dwContext : DWORD variable that contains the context value to use in

asynchronous operations.

 

6. InternetQueryDataAvailable

----------------------------------------------

BOOL InternetQueryDataAvailable(
IN HINTERNET hFile,
OUT LPDWORD lpdwNumberOfBytesAvailable,
IN DWORD dwFlags,
IN DWORD dwContext
);

----------------------------------------------

기본 설명 : 내용적으로 네크웍크카드를 통해서 들어온 데이터가 버퍼에 쌓이게 될 거이고,

그 버퍼의 양을 얻어내는 녀석이다. 결국 곧바로 파일로 저장하거나 읽어낼 때 이용

가능한 버퍼 사이즈를 얻어낸다.

대충 사용 방법 :

----------------------------------------------

HINTERNET hReq;

DWORD size;

InternetQueryDataAvailable(hReq, &size,0,0);

 

 

----------------------------------------------

인자 설명:

hFile : 조사할 버퍼의 핸들러 ( 여기서는 Http 요구 핸들러를 사용한다.)

lpdwNumberOfBytesAvailable : 받은 데이터의 버퍼 크기

dwFlags : must be zero (사용도 안 할 거면서 왜 있는 거야 훌훌..)

dwContext : must be zero

7. InternetReadFile

----------------------------------------------

BOOL InternetReadFile(
IN HINTERNET hFile,
IN LPVOID lpBuffer,
IN DWORD dwNumberOfBytesToRead,
OUT LPDWORD lpNumberOfBytesRead
);
----------------------------------------------

기본 설명 : 이름 그대로다 Internet정보를 읽는다.

대충 사용 방법 :

----------------------------------------------

HINTERNET hReq;

DWORD size;

DWORD dwRead;

char buf[65000];

InternetReadFile(hReq, buf, size,&dwRead);

 

 

----------------------------------------------

인자 설명:

hFile : 조사할 버퍼의 핸들러 ( 여기서는 Http 요구 핸들러를 사용한다.)

lpBuffer : 읽은 데이터를 저장할 버퍼

dwNumberOfBytesToRead : 읽고자 하는 데이터의 크기

lpNumberOfBytesRead : 실재 읽은 데이터의 크기

8. InternetWriteFile

----------------------------------------------

BOOL InternetWriteFile(
IN HINTERNET hFile,
IN LPCVOID lpBuffer,
IN DWORD dwNumberOfBytesToWrite,
OUT LPDWORD lpdwNumberOfBytesWritten
);
----------------------------------------------

기본 설명 : 오픈된 인터넷 파일에 쓴다.

대충 사용 방법 :

----------------------------------------------

HINTERNET hRequest;

DWORD dwBytesWritten;

char pBuffer[1024];

InternetWriteFile( hRequest, pBuffer, 1024, &dwBytesWritten);

 

 

----------------------------------------------

인자 설명:

hFile : Valid handle returned from a previous call to FtpOpenFile or an HINTERNET

handle sent by HttpSendRequestEx.

lpBuffer : 버퍼

dwNumberOfBytesToWrite : 쓰고자 하는 데이터의 크기

lpdwNumberOfBytesWritten : 실재 쓴 데이터의 크기

9. HttpEndRequest

----------------------------------------------

HttpEndRequest(
IN HINTERNET hRequest,
OUT LPINTERNET_BUFFERS lpBuffersOut,
IN DWORD dwFlags,
IN DWORD dwContext
);
----------------------------------------------

기본 설명 : Request를 종료한다. InternetWriteFile를 사용할 때 모든 파일이 전송되었다면

이를 호출해준다.

대충 사용 방법 :

----------------------------------------------

HINTERNET hRequest;

HttpEndRequest(hRequest, NULL, 0, 0)

 

 

----------------------------------------------

인자 설명:

hRequest : HINTERNET handle returned by HttpOpenRequest and sent by HttpSendRequestEx.

lpBuffersOut : Address of an INTERNET_BUFFERS structure

dwFlags :

HSR_ASYNC : Identical to WININET_API_FLAG_ASYNC.

HSR_SYNC : Identical to WININET_API_FLAG_SYNC.

HSR_USE_CONTEXT : Identical to WININET_API_FLAG_USE_CONTEXT.

HSR_INITIATE : Iterative operation (completed by HttpEndRequest).

HSR_DOWNLOAD : Download resource to file.

HSR_CHUNKED : Send chunked data.

dwContext : Double-word variable that contains the context value to use in

asynchronous operations

-----------------------------------------------------------------------

기본 예제

-----------------------------------------------------------------------
다음은 API 완전정복(가남사)의 구버전 P 1471에 있는 예제이다.

#include <windows.h>
#include <wininet.h>
#include <stdio.h>

void main() {
HINTERNET hInternet, hHttp;
HINTERNET hReq;
DWORD size;
DWORD dwRead;
char buf[65000];
char buf2[65000]={0,};

hInternet = InternetOpen("HTTPTEST",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
if(hInternet == NULL) {
printf("InternetOpen error\n");
return;
}

printf("InternetConnect\n");
hHttp = InternetConnect(hInternet,
"www.naver.com",
0,"","",
INTERNET_SERVICE_HTTP,
0,
0);
printf("HttpOpenRequest\n");
hReq = HttpOpenRequest(hHttp, "get","index.htm",NULL,NULL,NULL,0,0);
printf("HttpSendRequest\n");
HttpSendRequest(hReq,NULL,0,NULL,0);
do {
InternetQueryDataAvailable(hReq, &size,0,0);
InternetReadFile(hReq,buf,size,&dwRead);
buf[dwRead] = 0;
strcat(buf2,buf);
} while(dwRead != 0);

printf("[%s]\n",buf2);

InternetCloseHandle(hHttp);
InternetCloseHandle(hInternet);
}

-----------------------------------------------------------------------

기본 예제 HttpSendRequestEx를 사용

-----------------------------------------------------------------------

http://support.microsoft.com/kb/177188/ko 에서 제공하는 예제이다.

#include <Windows.h>
#include <WinINet.h>
#include <stdio.h>

BOOL UseHttpSendReqEx(HINTERNET hRequest, DWORD dwPostSize);
#define BUFFSIZE 500

void main( int argc, char **argv) {
DWORD dwPostSize;

if (argc < 4) {
printf("Usage: Bigpost <Size> <Server> <Path>\n");
printf("<Size> is the number of KB to POST\n");
printf("<Server> is the server to POST to\n");
printf("<Path> is the virtual path to POST to\n");
exit(0);
}

if ( ((dwPostSize = strtoul(argv[1],NULL,10)) == 0) || (dwPostSize >= 2047999) )
{
printf("%s is invalid size. Valid sizes are from 1 to 2047999\n", argv[1]);
exit(0);
}

printf( "Test of POSTing %luKB with WinInet\n", dwPostSize);

dwPostSize *= 1024; // Convert KB to bytes

HINTERNET hSession = InternetOpen( "HttpSendRequestEx", INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0);
if(!hSession)
{
printf("Failed to open session\n");
exit(0);
}


HINTERNET hConnect = InternetConnect(hSession, argv[2], INTERNET_DEFAULT_HTTP_PORT,
NULL, NULL, INTERNET_SERVICE_HTTP,NULL, NULL);
if (!hConnect)
printf( "Failed to connect\n" );
else
{
HINTERNET hRequest = HttpOpenRequest(hConnect, "POST", argv[3],
NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
if (!hRequest)
printf( "Failed to open request handle\n" );
else
{
if(UseHttpSendReqEx(hRequest, dwPostSize))
{
char pcBuffer[BUFFSIZE];
DWORD dwBytesRead;

printf("\nThe following was returned by the server:\n");
do
{ dwBytesRead=0;
if(InternetReadFile(hRequest, pcBuffer, BUFFSIZE-1, &dwBytesRead))
{
pcBuffer[dwBytesRead]=0x00; // Null-terminate buffer
printf("%s", pcBuffer);
}
else
printf("\nInternetReadFile failed");
}while(dwBytesRead>0);
printf("\n");
}
if (!InternetCloseHandle(hRequest))
printf( "Failed to close Request handle\n" );
}
if(!InternetCloseHandle(hConnect))
printf("Failed to close Connect handle\n");
}
if( InternetCloseHandle( hSession ) == FALSE )
printf( "Failed to close Session handle\n" );

printf( "\nFinished.\n" );
}

BOOL UseHttpSendReqEx(HINTERNET hRequest, DWORD dwPostSize)
{
INTERNET_BUFFERS BufferIn;
DWORD dwBytesWritten;
int n;
BYTE pBuffer[1024];
BOOL bRet;

BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS ); // Must be set or error will occur
BufferIn.Next = NULL;
BufferIn.lpcszHeader = NULL;
BufferIn.dwHeadersLength = 0;
BufferIn.dwHeadersTotal = 0;
BufferIn.lpvBuffer = NULL;
BufferIn.dwBufferLength = 0;
BufferIn.dwBufferTotal = dwPostSize; // This is the only member used other than dwStructSize
BufferIn.dwOffsetLow = 0;
BufferIn.dwOffsetHigh = 0;

if(!HttpSendRequestEx( hRequest, &BufferIn, NULL, 0, 0))
{
printf( "Error on HttpSendRequestEx %d\n",GetLastError() );
return FALSE;
}

FillMemory(pBuffer, 1024, 'D'); // Fill buffer with data

bRet=TRUE;
for(n=1; n<=(int)dwPostSize/1024 && bRet; n++)
{
if(bRet=InternetWriteFile( hRequest, pBuffer, 1024, &dwBytesWritten))
printf( "\r%d bytes sent.", n*1024);
}

if(!bRet)
{
printf( "\nError on InternetWriteFile %lu\n",GetLastError() );
return FALSE;
}

if(!HttpEndRequest(hRequest, NULL, 0, 0))
{
printf( "Error on HttpEndRequest %lu \n", GetLastError());
return FALSE;
}

return TRUE;
}

-----------------------------------------------------------------------

기본 예제 URL이 존재하는지 확인

-----------------------------------------------------------------------

bool
cs_util_http_test (const char* pURL,
const char* pObjectName)
{
HINTERNET hInternet, hHttp;
HINTERNET hReq;

/*--------------------------------------------------------------------*/
/* precondition
*/
/*--------------------------------------------------------------------*/
if( (pURL == NULL) ||
(pObjectName == NULL))
{
return false;
}

/*--------------------------------------------------------------------*/
hInternet = InternetOpen("HTTPTEST",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
if(hInternet == NULL)
{
return false;
}

hHttp = InternetConnect(hInternet,
pURL,
0,"","",
INTERNET_SERVICE_HTTP,
0,
0);
hReq = HttpOpenRequest(hHttp, "GET",pObjectName,NULL,NULL,NULL,0,0);
if(hReq == NULL)
return false;
if(!HttpSendRequest(hReq,NULL,0,NULL,0))
return false;

/*--------------------------------------------------------------------*/
DWORD size = 0;
DWORD dwRead = 0;
DWORD dwTotal = 0;
char sBuf[20];
do {
//InternetQueryDataAvailable(hReq, &size,0,0);
InternetReadFile(hReq, sBuf, 10, &dwRead);
dwTotal += dwRead;
printf("%s",sBuf);
if(dwTotal>10)break;
} while(dwRead != 0);

InternetCloseHandle(hHttp);
InternetCloseHandle(hInternet);

if(dwTotal > 10)
{
return true;
}
return false;
}

댓글