Створення простого HTTP-клієнта h2>
У цій статті напишуть програму, яка може
зчитувати файли з Internet по HTTP протоколу і записувати їх на диск. p>
Для зв'язку з Internet в Visual C + + існує так
званий WinInet Class. У нього входять декілька підкласів. P>
Далі представлені ксасси WinInet: p>
Класи Опис p>
CInternetSession Створює Internet сесію. Всі MFC
WinInet додатки повинні створювати CInternetSession об'єкт перед
іспользрваніем інших WinInet класів. p>
CInternetConnection
Створює конект із Internet. Це базовий клас для класів CFtpConnection,
CGopherConnection, і CHttpConnection. p>
CFtpConnection Встановлює з'єднання по FTP
протоколу. p>
CGopherConnection Створює Gopher підключення. p>
CHttpConnection Встановлює з'єднання по HTTP
протоколу. p>
CInternetFile Дозволяє віддалений доступ до файлів на
Internet серверах. Це базовий клас для класів CGopherFile and CHttpFile. p>
CGopherFile Дозволяє віддалений доступ до файлів на
Gopher серверах. p>
CHttpFile Дозволяє віддалений доступ до файлів на HTTP
серверах. p>
CFileFind Дозволяє шукати файли в Internet. Це
базовий клас для класів CFtpFileFind and CGopherFileFind. p>
CFtpFileFind Дозволяє шукати файли на FTP серверах. p>
CGopherFileFind Дозволяє шукати файли на Gopher
серверах. p>
CGopherLocator відшукує Gopher пристрій вводу
Що gopher сервера. p>
CInternetException Управляє винятками,
згенерований WinInet класом. p>
Наша програма буде використовувати чотири класи
WinInet: CInternetSession, CInternetFile, CHttpFile і CHttpConnection p>
Далі будуть описані методи (функції) цих класів: p>
Методи (функції) класу CInternetSession p>
Опції Опис p>
Close () Закриває Internet сесію. p>
EnableStatusCallback () Дозволяє використовувати функцію
повторного виклику, яка використовується для асинхронних дій. p>
GetContext () Отримує значення контексту Internet
сесії. p>
GetFtpConnection () Встановлює підключення по FTP
протоколу. p>
GetGopherConnection () Встановлює підключення з
Gopher серверами. p>
GetHttpConnection () Встановлює підключення по HTTP
протоклолу. p>
OnStatusCallback () модифікує стан операції. p>
OpenURL () З'єднується з даними URL. p>
QueryOption () Сервіс перевірки помилки провайдера. p>
ServiceTypeFromHandle () Отримує тип сервісу від
Internet дескриптора. p>
SetOption () Встановлює опції Internet сесії. p>
Методи (функції) класу CInternetFile p>
Опції Опис p>
Abort () Закриває файл і ігнорує всі помилки. p>
Close () Закриває файл. p>
Flush () Скидає файл на диск. p>
Read () Счативает байт з файлу. p>
ReadString () зчитує рядок символів з файлу. p>
Seek () перевстановлюємо покажчик усередині файлу. p>
SetReadBufferSize () Встановлює розмір буферу для
читання. p>
SetWriteBufferSize () Встановлює розмір буферу для
запису. p>
Write () Записує байт в файл. p>
WriteString () Записує рядок з нульовим символом в
Наприкінці у файл. p>
Методи (функції) класу CHttpFile p>
Опції Опис p>
AddRequestHeaders () Додає заголовок до HTTP
запитом. p>
Close () Закриває CHttpFile об'єкт. p>
GetFileURL () Отримує URL файлу. p>
GetObject () Отримує об'єкт по HTTP запиту. p>
GetVerb () Отримує заголовок запиту. p>
QueryInfo () Отримує відповідь або заголовок запиту. p>
QueryInfoStatusCode () Отримує код стану HTTP
запиту. p>
SendRequest () Посилає HTTP запит. p>
Далі напишемо код програми і розберемо кожен рядок: p>
... p>
CString m_url =
"mark5.dhtp.kiae.ru";// ім'я URL p>
CString m_mes;// мінлива в якій будуть зберігатися
повідомлення p>
char temp [100];// проміжна змінна для
перекладу p>
// даних з Int в char p>
CString m_path;// ім'я файлу для запису p>
char strBody [1024];// буфер з 1024 байт p>
... p>
int CHTTP_ClientDlg:: OnButtonConnect () p>
( p>
// створюємо змінну session і відкриваємо сесію ANDY p>
CInternetSession
session (_T ( "ANDY"), PRE_CONFIG_INTERNET_ACCESS); p>
// створюємо змінну pServer класу CHttpConnection p>
CHttpConnection *
pServer = NULL; p>
// створюємо змінну pFile класу CHttpFile p>
CHttpFile * pFile =
NULL; p>
/* p>
Зверніть увагу, що всі запити до функцій членам
WinInet класів включені в блок програми TRY. P>
Це зроблено так, тому що при з'єднанні з яким
або URL є ризик неправильної посилання, p>
особливо, коли Ви вважаєте, що користувач сам
друкує URL. p>
Інша проблема - часи очікування, які виникають,
коли потрібний URL в даний час p>
нездатний обслужити підключення. p>
Так само обробка WinInet винятків, які
представлені в класі p>
CInternetException, є важливою частиною створення
Internet додатки під MFC. P>
*/ p>
try p>
( p>
CString
strServerName;// ім'я сервера p>
CString strObject;
//Ім'я об'єкта p>
INTERNET_PORT nPort;// номер порту для зв'язку p>
DWORD dwServiceType;// тип сервісу p>
// функція AfxParseURL отримує дані з вказаного
URL (у нас m_url) про сервер, p>
// об'єкті, тип сервісу і порте p>
if (AfxParseURL (m_url, dwServiceType, strServerName,
strObject, nPort) == 0) p>
( p>
return 1;// вихід із функції OnButtonConnect () p>
) p>
// вивід даних про сервер p>
m_mes = ""; p>
m_mes + =
"Server Name ="; p>
m_mes + =
(CString) strServerName; m_mes + = "rn"; p>
m_mes + =
"Object Name ="; p>
m_mes + =
(CString) strObject; m_mes + = "rn"; p>
m_mes + = "Port
= "; P>
itoa (nPort, temp,
10); p>
m_mes + =
(CString) & temp [0]; m_mes + = "rn"; p>
UpdateData (FALSE); p>
// Встановлюємо підключення по HTTP протоклолу. p>
pServer =
session.GetHttpConnection (strServerName, nPort); p>
// посилаємо запит про об'єкт (strObject) p>
pFile =
pServer-> OpenRequest ( p>
CHttpConnection:: HTTP_VERB_GET,
strObject, NULL, 1, NULL, NULL, p>
INTERNET_FLAG_EXISTING_CONNECT
| INTERNET_FLAG_NO_AUTO_REDIRECT p>
); p>
// Додаємо заголовок до HTTP запиту p>
pFile-> AddRequestHeaders (
_T ( "Accept: */* rnUser-Agent: ANDYrn")); p>
// посилаємо запит p>
pFile-> SendRequest (); p>
DWORD dwRet;// змінна для збереження коду стану
p>
pFile-> QueryInfoStatusCode (dwRet);// записуємо
код стану в dwRet p>
// вивід даних p>
m_mes + = "The
HTTP GET returned a status code of "; p>
itoa (dwRet, temp,
10); p>
m_mes + =
(CString) & temp [0]; m_mes + = "rn"; p>
CString strHeader;// змінна для зберігання
отриманого заголовок запиту p>
pFile-> QueryInfo (HTTP_QUERY_RAW_HEADERS_CRLF,
strHeader);// записуємо заголовок у strHeader p>
// вивід даних p>
m_mes + =
"Header ="; p>
m_mes + = strHeader;
p>
UpdateData (FALSE); p>
// якщо код стану не дорівнює 200, то виходимо з
функції p>
if (dwRet! = 200)
(M_mes + = "Program terminate!"; UpdateData (FALSE); return 1;) p>
//
-------------------------------------------------- -------- p>
// перевірка вибору файлу для запису p>
m_mes + =
"Starting download the file."; M_mes + = "rn"; p>
if (m_path ==
"") P>
( p>
m_mes + =
"Error! No file to save. Choese the file ."; p>
m_mes + =
"rn"; UpdateData (FALSE); return 1;) p>
else p>
( p>
m_mes + = "File
name to save: "; p>
m_mes + = m_path;
m_mes + = "rn"; UpdateData (FALSE); p>
) p>
CFile file2;// оголошуємо змінну file2 класу
CFile p>
// відкриваємо файл для запису в двійковому форматі (
CFile:: typeBinary) !!! p>
file2.Open ((LPCTSTR) m_path, p>
CFile:: modeCreate | CFile:: modeWrite | CFile:: typeBinary); p>
int allRead = 0;// змінна для зберігання загального
числи лічених байт p>
int nRead = pFile-> Read (strBody, 1024);//
зчитуємо перших 1024 байта в буфер. p>
// мінлива nRead зберігає кількість p>
// лічених байт p>
allRead + = nRead;// оновлюємо загальне число лічених
байт p>
// вивід даних p>
m_mes + =
"Loading"; p>
itoa (nRead, temp,
10); p>
m_mes + =
(CString) & temp [0]; m_mes + = "bytes"; m_mes + = "rn"; p>
UpdateData (FALSE); p>
// записуємо буфер з nRead байт в файл p>
file2.Write (strBody, nRead); p>
// цикл зчитування, поки nRead не буде дорівнювати нулю p>
while (nRead>
0) p>
( p>
nRead =
pFile-> Read (strBody, 1024); p>
if (nRead! = 0) p>
( p>
m_mes + =
"Loading"; p>
itoa (nRead, temp,
10); p>
m_mes + = (CString) & temp [0];
m_mes + = "bytes"; m_mes + = "rn"; p>
file2.Write (
strBody, nRead); p>
allRead + = nRead; p>
UpdateData (FALSE
); p>
) p>
) p>
// вивід даних p>
m_mes + =
"rn"; p>
m_mes + =
"Total bytes ="; p>
itoa (allRead,
temp, 10); p>
m_mes + =
& temp [0]; m_mes + = "rn"; UpdateData (FALSE); p>
file2.Close ();// закриваємо файл p>
pFile-> Close ();
//Закриваємо Internet файл p>
pServer-> Close ();
//Закриваємо сервер p>
m_mes + =
"Download is complete !!!"; m_mes + =" rn "; UpdateData (FALSE
); p>
) p>
catch (CInternetException *
pEx) p>
( p>
// Якщо сталася помилка в WinInet p>
// вивід помилки p>
char szErr [1024]; p>
pEx-> GetErrorMessage (
szErr, 1024); p>
m_mes + =
"Error: ("; p>
itoa (
int (pEx-> m_dwError), temp, 10); p>
m_mes + =
(CString) & temp [0]; p>
m_mes + = ")
"; p>
m_mes + =
(CString) & szErr [0]; m_mes + = "rn"; p>
UpdateData (FALSE
); p>
pEx-> Delete ();
//Видалення змінної класу CInternetException p>
if (pFile! = NULL
) p>
delete pFile;// закриваємо Internet файл p>
if (pServer! =
NULL) p>
delete pServer;
//Закриваємо сервер p>
session.Close ();// закриваємо
сесію p>
return 1; p>
) p>
if (pFile! = NULL
) p>
delete pFile;// закриваємо Internet файл p>
if (pServer! =
NULL) p>
delete pServer;// закриваємо сервер p>
session.Close ();// закриваємо сесію p>
return 0; p>
) p>
Ну от і все, додаток готове. p>
Список літератури h2>
Для підготовки даної роботи були використані
матеріали з сайту http://www.realcoding.net/
p>