WinInet(The Microsoft Win32 Internet functions) 클래스는 Win32
반의 WinInet API들을 캡슐화하고 있는 클래스의 모임을 말하며 클
라이언트 쪽에서 인터넷의 표준 프로토콜인 HTTP, Gopher, FTP
등을 지원하기 위한 클래스이다. MFC에서 제공하는 WinInet 관련
클래스들은 네트워크상에서 발생하는 여러 가지 복잡한 처리 작업
을 내부적으로 수행하고 상당히 안정적인 코드를 제공한다. 이러한
프로토콜을 사용한 전송을 쉽게 할 수 있도록 운영체제 확장의 일부
로 wininet.dll을 제공한다. MFC 응용 프로그램에서 wininet.dll은
CInternetSession 개체에 의해 표현된다. CInternetSession은 작업
자가 인터넷에 정확히 어떻게 연결하려고 했는지 wininet.dll에게
알리도록 한다.
CInternetSession(LPCTSTR pstrAgent = NULL, DWORD dwCont
ext = 1, DWORD dwAccessType = INTERNET_OPEN_TYPE_PRE
CONFIG, LPCTSTR pstrProxyName = NULL, LPCTSTR pstrProxy
Bypass = NULL, DWORD dwFlags = 0);
첫 번째 인자는 클라이언트 쪽 소프트웨어 이름을 가리키는 포인터
이다. 디폴트값 NULL은 생성자가 AfxGetAppName() 호출을 통해
응용프로그램의 이름을 찾게 할 것이다. dwAccessType 인자는 Wi
nInet에게 인터넷을 어떻게 연결할 계획인지 알려준다. 디폴트 값인
INTER_OPEN_TYPE_PRECONFIG는 레지스트리에서 인터넷 연결
에 관하여 이전에 입력된 정보를 찾는다. 인트라넷을 사용하고 있거
나 컴퓨터가 인터넷에 직접 연결되어 있다면 INTERNET_OPEN_TY
PE_DIRECT를 지정할 수 있다. 방화벽을 통한 연결은 GATEWAY_I
NTERNET_ACCESS, 프록시를 통해 인터넷에 요청을 전달하려고
하려면 INTERNET_OPEN_TYPE_PROXY를 지정한다. 이것을 지정
하지 않으면 pstrProxyName과 pstrProxyBypass 인자를 NULL로
지정할 수 있다. 그리고 dwFlags 인자를 사용하여 다른 방법으로
연결에 영항을 줄 수 있다. 비동기 동작을 지원하는 INTERNET_FL
AG_ASYNC 플래그와 세션을 통해 기존 연결을 재사용하려는 INTE
R_FLAG_EXITING_CONNECT 플래그가 OR 연산자를 사용하여 결
합된다.
dwContext라는 인자가 있는데 인터넷에 있는 다른 컴퓨터와 대화
하는 것은 오랜 시간이 걸릴 수 있다. 일부 프로토콜 등은 많은 오버
헤드를 발생시키고, 인터넷 응용 프로그램의 사용자들은 종종 느린
링크를 통해서 연결된다. 따라서 윈도우 인터넷 API는 언제, 어떤
것이 진행되었는지 응용프로그램이 알 수 있게 하는 콜백을 제공한
다. dwContext 인자는 단순히 응용 프로그램이 실행하고 있는 각
동작들을 구분할 수 있게 해준다. MFC는 콜백 함수처럼 복잡한 것
들에 대해 염려하지 않아도 되게 해준다. CInternetSession으로부
터 클래스를 유도하고 OnStatusCallback() 함수를 오버라이드할
수 있다.
또 CInternetSession 듀도 개체에 EnableStatusCallback() 함수를
호출하여 상태 콜백을 받고 싶어한다는 것을 시스템에게 알릴 필요
가 있다. 이 인자가 TRUE(디폴트)이면 함수가 콜백을 활성화시킬
것이고, FALSE이면 인자가 콜백을 비활성화시킬 것이다. CInternet
Session을 열고 FTP 프로토콜을 이용하여 파일을 전송할 경우 Get
FtpConnection() 멤버를 호출함으로써 CFtpConnection 개체를 생
성할 수 있다. GetFtpConnection()은 이 새 CFtpConnection을 가
리키는 포인터를 반환한다.
CFtpConnection* GetFtpConnection( LPCTSTR pstrServer, LPC
TSTR pstrUserName = NULL, LPCTSTR pstrPassword = NULL, I
NTERNET_PORT nPort = INTERNET_INVALID_PORT_NUMBER, B
OOL bPassive = FALSE );
첫 번째 인자는 연결하고자 하는 서버의 이름이고 두 번째 인자와
세 번째 인자는 연결에 사용될 사용자 이름과 암호를 나타낸다. 디
폴트 값인 NULL을 전달하면 익명(anonynous)으로 접속요청을 하
게 된다. nPort 인자는 포트 번호를 나타내는데 디폴트 값인 INTER
NET_INVALID_PORT_NUMBER을 사용하면 이 프로토콜의 디폴트
TCP/IP 포트 번호(HTTP:80, FTP:21, Gopher:70, HTTPS:443)를 사
용한다. 이를 이용한 FTP 서버 접속은 리스트 3과 같다.
리스트 3 : FTP 서버 접속
------------------------------------------------------------
CInternetSession m_Session;
CFtpConnection *m_pConnection = NULL;
try
{
//Anonymous 로 로그인
m_pConnection = m_Session.GetFtpConnection("ftp.pserang.co.
kr");
// 사용자명과 패스워드 로그인
/* m_pConnnection = m_Session.GetFtpConnection("ftp.pseran
g.co.kr","User_Name","Password"); */
//연결시 작업
m_pConnection->Close();
}
catch (CInternetException *m_pEx)
{
m_pEx->ReportError(MB_ICONEXCLAMATION);
m_pConnection = NULL;
m_pEx->Delete();
}
delete m_pConnection;
------------------------------------------------------------CInternetException은 운영체제로부터 문제를 기술하는 에러 텍스
트를 얻어내는 에외처리 클래스이다. 연결이 이루어 졌을 때 GetCu
rrentDirectory()를 호출하여 FTP 컴퓨터의 현재 디렉토리를 얻을
수 있고 SetCurrentDirectory()로 상대편 디렉토리를 설정할 수 있
다. 그리고 GetFile()로 파일을 다운로드 할 수 있고 PutFile()로 파
일을 업로드 할 수 있다. 사용자에게 권한이 주어지면 CreateDirect
ory()/RemoveDirectory() 및 Remove()/Rename()를 호출하여 디
렉토리를 생성/추가할 수 있고 파일을 제거/이름변경을 할 수 있다.
예를 들어 파일을 다운로드 할 때의 코드는 다음과 같다.
m_pConnection->GetFile("RemoteFile", "localFile", FALSE,
FILE_ATTRIBUTE_NORMAL,
FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_
RELOAD | INTERNET_FLAG_NO_CACHE_WRITE);
네 번째 인자(DWORD dwAttributes)는 파일 복사 후 로컬 컴퓨터에
생성되는 파일의 속성을 나타낸다. 읽기 전용은 FILE_ATTRIBUTE_
READONLY로 지정할 수 있다. 다섯 번째 인자(DWORD dwFlags)
는 원시 이진 파일들을 처리할 수 없는 연결을 통해 올바로 데이터
를 전달하기 위해 FTP 프로토콜에 사용되는 의미를 바꾼다. CFtpFi
leFind란 클래스가 있는데 FTP 서버를 검색하는 기능을 수행한다.
이 클래스는 CFileFind 클래스에서 파생되었다. CFtpFileFind 클래
스는 두 개의 인자가 있는데 첫 번째 인자는 검색할 서버를 위한 CF
tpConnectiondmf 가리키는 포인터이고 두 번째 인자는 dwContext
값을 나타낸다.
CFtpFileFind *m_pFileFind = NULL;
m_pFileFind = new CFtpFileFind(m_pConnection);
BOOL bContinue = TRUE;
CString m_file_name;
m_pFileFind->FindFile("RemoteDir");
while(bContinue)
{
bContinue = m_pFileFind->FindNextFile();
m_file_name = m_pFileFind->GetFileName();
if(m_pFileFind->IsDirectory())
{
//디렉토리일 경우 루틴
}
// 파일인 경우
else
{
//파일일 경우 루틴
}
}
FTP 서버로 연결이 되면 CFtpFileFind 클래스를 이용하여 지정된
경로의 파일을 계속 찾는 구문이다. HTTP 서버 즉, 일반적으로 말
하는 웹 서버에 접속하기 위해서 MFC 계층에서 CFtpConnection
과 비슷한 위치를 차지하는 CHttpConnection를 사용해 연결할 수
있다. CInternetSession의 GetHtpConnection() 멤버를 사용하여 C
HttpConnection을 열 수 있다.
CHttpConnection* GetHttpConnection( LPCTSTR pstrServer, INT
ERNET_PORT nPort = INTERNET_INVALID_PORT_NUMBER, LPC
TSTR pstrUserName = NULL, LPCTSTR pstrPassword = NULL );
각 인자는 GetFtpConnection()과 거의 동일하다. 웹서버에 접속하
는 코드는 다음과 같다.
CInternetSession m_Session;
CHttpConnection *m_pHttpConnection = NULL;
CHttpFile *m_pFile = NULL;
try
{
m_pHttpConnection = m_Session.GetHttpConnection("www.pser
ang.co.kr");
m_pFile = m_pHttpconnection->OpenRequest(CHttpConnection::
HTTP_VERB_GET,"/");
m_pFile -> AddRequestHeaders("Accept:text/*\r\nAccept-La
nguage:kr\r\n");
m_pFile ->SendRequest();
//...
}
catch(CInternetException *m_pEx)
{
m_pEx->ReprotError();
m_pEx->Delete();
}
delete m_pFile;
delete m_pHttpConnection;
CHttpFile이라는 것이 있는데 CInternetFile로부터 유도되었고 CInt
ernetFile은 CStdioFile로부터 유도되었다. CHttpFile의 특징은 자신
만의 파일 데이터 버퍼링을 수행한다. SetReadBufferSize()를 호출
하여 버퍼 크기를 설정할 수 있고, 버퍼를 설정하지 않고서 ReadStr
ing()을 사용하면 자동으로 버퍼가 설정된다. 위 코드 중 서버에게
요청하는 OpenRequest()의 첫 번째 인자는 CHttpConnection 내부
의 enum에서 정의된 기호이다. 이 인자는 요청에서 사용하고자 하
는 메소드를 지정한다. HTTP_VERB_GET이라는 메소드는 서버에
있는 개체의 전체 내용을 요청하는데 쓰인다. 그 외 특정 개체와 연
결된 개체를 전달하고자 할 때는 HTTP_VERB_POST 인자가 쓰이
고 마지막 인자인 POST 대신 HEAD, PUT, LINK, DELETE, UNLINK
등이 사용된다.
요청은 CHttpFile::SendRequest() 호출과 함께 전달된다. 요청을
전달하기 전에 헤더를 추가하고 싶으면 CHttpFile::AddHeaders()
를 호출할 수 있다. 서버가 요청에 대한 개체를 갖고 있지만 클라이
언트의 Accept: 헤더에서 지정된 형식 요청을 충족시킬 수 없으면
일반 "404 Not Found"(HTTP_STATUS_NOT_FUOND: 404)" 에러와
"HTTP_STATUS_NONE_ACCEPTABLE: 406" 에러를 반환할 것이
다. 요청이 전달되고 반응이 성공적으로 수신되었으면 SendReque
st()가 TRUE를 반환한다. 그렇지 않으면 예외가 발생할 것이다. 이
것은 내부 서버 에러가 있다는 것을 의미한다. CHttpFile::QueryInfo
StatusCode()를 호출함으로써 CHttpFile 개체로 들어온 정보로부
터 반환 코드를 커낼 수 있다.
m_pFile->SendRequest();
DWORD m_dwStatusCode;
m_pFile->QueryInfoStatusCode(m_dwStatusCode);
m_dwStatusCode는 요청 결과에 반영하는 정수를 갖고 있다. 예를
들어 200은 HTTP_STATUS_OK를 나타내며 요청이 게이트웨이로
갔지만 게이트웨이와 서버와의 통신이 타임아웃일 경우는 504(HTT
P_STATUS_GATEWAY_TIMEOUT)를 나타낸다
리스트 4는 프록시를 통하여 HTTP 파일을 다운로드 하는 코드이다.
댓글 없음:
댓글 쓰기