이 글을 보기 전에 이전 글 먼저 봐주시기 바랍니다.
저번 글에 이어서 오늘은 json과 xml을 받아오는 방법을 알아보겠습니다.
총 두 가지 방법이 있는데 두 가지 방법 다 알아보겠습니다.
MFC 프로젝트를 하나 생성해 주시고 아래와 같이 컨트롤을 배치해 놓습니다.
URL 우측 에디트 박스에 아래 그림과 같이 URL을 입력할 예정입니다. 빨간색은 제 인증키입니다.
1. CInternetSession
첫 번째 방법은 CInternetSession을 이용하는 방법입니다. 해당 방법이 더 코드가 짧고 쉽습니다.
CInternetSession을 사용하시려면 아래 헤더파일을 입력해야합니다.
#include <afxinet.h>
CInternetSession 버튼을 더블 클릭하여 아래와 같이 코딩합니다.
void CMFCApplication1Dlg::OnBnClickedButtonCInternetSession()
{
UpdateData(TRUE);
// 세션이 연결된 이후, 웹 사이트의 Html 정보가 변경된 사항을 가져올 경우
CInternetSession session( NULL, 1, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_DONT_CACHE );
try
{
// 세션 클래스를 이용하여 열기
CInternetFile *pinetFile = (CInternetFile *)session.OpenURL( m_sUrl );
if ( NULL != pinetFile )
{
char acRead[40960] = { 0, }; // return 값이 길 수 있으므로 충분히 입력
memset( acRead, 0, sizeof( acRead ) );
// json 읽는 부분
UINT uiTotalRead = 0;
int iIdex = 0;
do
{
// 데이터를 1024씩 읽어 온다.
uiTotalRead = pinetFile->Read( &acRead[iIdex], 1024 );
if ( uiTotalRead <= 0 )
break;
iIdex += uiTotalRead;
} while ( uiTotalRead > 0 );
// 읽은 json 표시를 위한 부분
std::string strJson = acRead;
m_sResult = CA2W( strJson.c_str(), CP_UTF8 );
pinetFile->Close(); // Html 파일을 닫는다.
session.Close(); // 세션 종료
delete pinetFile; // Html 파일 읽기에 사용한 객체를 파괴
}
}
catch ( CInternetException *e )
{
// 에러
}
UpdateData( FALSE );
}
2. HttpSendRequest
두번째 방법은 좀 더 복잡합니다.
우선 먼저 아래 헤더파일과 라이브러리를 추가합니다.
#include <WinInet.h>
#pragma comment(lib, "Wininet.lib")
HttpSendRequest 버튼을 더블클릭하여 아래와 같이 코딩합니다.
void CMFCApplication1Dlg::OnBnClickedButtonHttpSendRequest()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
UpdateData( TRUE );
TCHAR szHostName[INTERNET_MAX_HOST_NAME_LENGTH + 1] = { 0, };
TCHAR szUrlPath[INTERNET_MAX_PATH_LENGTH + 1] = { 0, };
TCHAR szExtraInfo[INTERNET_MAX_PATH_LENGTH + 1] = { 0, };
URL_COMPONENTS urlComponents;
memset( &urlComponents, 0, sizeof( URL_COMPONENTS ) );
urlComponents.dwStructSize = sizeof( URL_COMPONENTS );
urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
urlComponents.lpszHostName = szHostName;
urlComponents.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH;
urlComponents.lpszUrlPath = szUrlPath;
urlComponents.dwExtraInfoLength = INTERNET_MAX_PATH_LENGTH;
urlComponents.lpszExtraInfo = szExtraInfo;
TCHAR szUrl[40960] = { 0, };
_tcscpy_s( szUrl, 40960, m_sUrl );
InternetCrackUrl( szUrl, 0, ICU_DECODE, &urlComponents ); // 입력한 url을 분해
// internet open
HINTERNET hInternet = ::InternetOpen( _T( "Seoul Open API Test" ), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
if ( hInternet != NULL )
{
// internet connect
HINTERNET hConnect = ::InternetConnect( hInternet, urlComponents.lpszHostName, urlComponents.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1 );
if ( hConnect != NULL )
{
DWORD dwFlags = INTERNET_FLAG_RELOAD;
// http open request
HINTERNET hRequest = ::HttpOpenRequest( hConnect, NULL, urlComponents.lpszUrlPath, HTTP_VERSION, NULL, NULL, dwFlags, 0 );
if ( hRequest != NULL )
{
// http send request
BOOL bRequest = FALSE;
bRequest = ::HttpSendRequest( hRequest, NULL, 0, NULL, 0 );
if ( bRequest )
{
char acRead[40960] = { 0, };
// return 데이터
BYTE *pbyBuffer = (BYTE *)acRead;
DWORD dwLen = 0;
int nCount = 0;
while ( true )
{
::InternetReadFile( hRequest, pbyBuffer + nCount, 1024, &dwLen );
if ( dwLen <= 0 )
break;
nCount += dwLen;
}
pbyBuffer[nCount] = 0;
std::string strJson = acRead;
m_sResult = CA2W( strJson.c_str(), CP_UTF8 );
}
::InternetCloseHandle( hRequest );
}
::InternetCloseHandle( hConnect );
}
::InternetCloseHandle( hInternet );
}
UpdateData( FALSE );
}
프로그램 실행 후 보시면 아래와 같이 같은 문자열이 출력 됩니다.
xml은 URL에서 json부분을 xml으로 변경하시면 됩니다.
http://openapi.seoul.go.kr:8088/sample/xml/bikeList/1/5/
json과 xml은 서울시에서 제공해줘야 받을 수 있습니다. 자전거 실시간 대여 상황 xml도 지원해준다고 써져있는데 되지 않네요.
웹 관련 공부를 해본적이 없어 개념에 대해 자세히 설명을 드릴 순 없지만 결국은 요청한 URL에 대해 결과를 받아오는 방식입니다.
첫번째, 두번째에 사용된 CInternetFile::Read나 InternetReadFile로 파일을 다운받을 수도 있습니다.
어쨌든 json과 xml을 읽었고, 다음 글에서는 json을 파싱하는 법에 대해 알아보도록 하겠습니다.