Если твои сиприплюснутые программы когда-нибудь нуждались в широких и гибких автоматизированных возможностях работы с интернет-ресурсами, то настоятельно рекомендую прочитать этот захватывающий рассказ о самой простой их реализации. Почему простой? Да потому, что в программировании все, как в жизни – сложно и ничего не понятно… но только до тех пор, пока сам не попробуешь.
В этой статье я покажу, как легко интегрировать и использовать функции библиотеки libcurl в программу на C++ (Builder 6 C++ ). Кроме того, мы рассмотрим некоторые основы работы с libcurl: работу по протоколам HTTP и HTTPS, формирование запросов, работу через разные типы прокси с возможностью авторизации, отправку данных методом POST и GET, а также настройку работы с cookies. Все возможности библиотеки libcurl рассматривать, думаю, не стоит, главное - понять принципы.
В этой статье я покажу, как легко интегрировать и использовать функции библиотеки libcurl в программу на C++ (Builder 6 C++ ). Кроме того, мы рассмотрим некоторые основы работы с libcurl: работу по протоколам HTTP и HTTPS, формирование запросов, работу через разные типы прокси с возможностью авторизации, отправку данных методом POST и GET, а также настройку работы с cookies. Все возможности библиотеки libcurl рассматривать, думаю, не стоит, главное - понять принципы.
Немного о проекте cURL
Впервые проект под именем cURL (client URL) появился 20 марта 1998 года. Создатель столь замечательного инструментария - Даниэль Стенберг(Daniel Stenberg). Его страничка находится по адресу http://daniel.haxx.se. Кстати, почему именно cURL? В чем его особенность? Дело в том, что он представляет собой полный возможностей, удобный и гибкий инструмент по работе с различного рода интернет-ресурсами, который можно свободно использовать в своих программах в качестве подключаемого дополнения или основного механизма. Общение и управление cURL осуществляется посредством предоставленного им же гибкого и удобного API-интерфейса. Проект cURL – абсолютно бесплатный и сам по себе представлен двумя реализациями: cURL-инструментарий для командной строки и динамическая библиотека DLL «Libcurl» - libcurl.dll . Нас интересует именно библиотека. Фишки libcurl не могут не радовать. Это и поддержка FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS, сертификатов SSL, POST HTTP, PUT HTTP; поддержка работы через разные типы proxy (HTTP + возможность туннелирования, Socs4, Socs5) с возможностью авторизации, работа с cookies и др. Кроме всего прочего, cURL – кроссплатформенный проект и работает на многих UNIX-совместимых платформах, Mac OS X и Windows. Для более детального ознакомления советую посетить http://curl.haxx.se.
Шаг первый - прикрепляем проект libcurl к Builder C++
Итак, будем надеяться, что на своем компьютере ты располагаешь, как минимум, Windows XP (точнее, любой win32, желательно начиная от Windows2000). Первое, что тебе понадобится - это среда программирования, а именно Builder 6 C++ (впрочем, можно брать любую версию). Заимев ее, можно смело следовать на официальный сайт cURL в раздел «Download» по адресу: http://curl.haxx.se/download.html, найти там раздел «Win32-Generic» и скачать последнюю версию библиотеки «libcurl».
Теперь, когда мы скачали архив с проектом libcurl, распакуем его и обратим внимание на вложенные папки. Папка Bin таит в себе все необходимые для работы файлы *.dll (прилагающийся curl.exe не нужен). Скопируем их из этой папки в папку Bin каталога Builder C++. Затем в корневом каталоге скачанной libcurl найдем под-подкаталог curl по адресу \Include\curl – это каталог заголовков, которые включают в проект по мере необходимости при компиляции программы. Копируем этот каталог в каталог Include директории Builer C++. Все. На этой торжественной ноте мы можем перейти к следующему этапу – водным процедурам!
Шаг второй. Объявление easy – интерфейса проекта libcurl
Итак, у нас уже есть установленная среда программирования Builder C++ с прикрученной библиотекой libcurl последней версии. Теперь запустим Builder и перетянем на форму проекта кнопку button1, – кликнем по ней два раза, чтобы открылся редактор кода на месте обработчика события кнопки. Прилинкуем библиотеку libcurl.dll проекта libcurl - пишем код в обработчике события кнопки:
Прилинковка библиотеки libcurl.dll в проекте
HINSTANCE cl = NULL;
if( ( cl = LoadLibrary( "libcurl.dll" ) ) ==
NULL )
\\ загружаем библиотеку
MessageBox(NULL, "I can't load
libcurl","ERROR", 0);
\\если нельзя загрузить
FreeLibrary(cl);Как же нам обратиться к libcurl? Используют специальные API-функции и нам необходимо их объявить, чтобы реализовать диалог между нашей программой и libcurl-функцией так называемого easy-интерфейса (для справки загляни на страничку http://curl.haxx.se/libcurl/c, где можно посмотреть, что они из себя представляют и как объявляются).
Затем давай включим в начало нашего проекта заголовочный файл curl/ curl.h строчкой #include <curl/curl.h. После кода прилинковки libcurl.dll запишем код объявления easy-интерфейса в нашей программе.
Код объявления с адресацией функций easy-интерфейса проекта libcurl
\\ объявление указателей на функции
CURL*(__stdcall *curl_easy_init)();
CURLcode(__stdcall *curl_easy_setopt )
(CURL *curl, CURLoption option, ...);
CURLcode (__stdcall *curl_easy_perform )
(CURL *curl);
CURLcode(__stdcall *curl_easy_getinfo )
(CURL *curl, CURLINFO info, ...);
void (__stdcall *curl_easy_cleanup )
(CURL *curl);
struct curl_slist *(__stdcall
*curl_slist_append )
(struct curl_slist *list,const char *string);
void (__stdcall *curl_slist_free_all)
(struct curl_slist * list);\\ присваиваем указателям функций соответствующие адреса функции DLL
curl_easy_init
=(CURL*(__stdcall*)())GetProcAddress(cl,
"curl_easy_init" );
curl_easy_setopt =(CURLcode(__stdcall *)(CURL
*curl, CURLoption option, ...))
GetProcAddress(cl, "curl_easy_setopt");
curl_easy_perform =(CURLcode(__stdcall *)(CURL
*curl))GetProcAddress(cl, "curl_easy_perform"
);
curl_easy_cleanup =(void (__stdcall *)(CURL
*curl))GetProcAddress(cl, "curl_easy_cleanup"
);
curl_easy_getinfo=(CURLcode(__stdcall *)
(CURL *curl, CURLINFO info,
...))GetProcAddress
(cl, "curl_easy_getinfo");
curl_slist_append=(curl_slist*(__stdcall *)
(struct curl_slist *list,const char
*string))GetProcAddress(cl,"curl_slist_append"
);
curl_slist_free_all=(void(__stdcall *)
(struct curl_slist *list))GetProcAddress
(cl,"curl_slist_free_all");Поскольку мы используем динамическую, а не статическую загрузку библиотеки, нам необходимо прибегнуть к такого рода объявлениям и адресации функций. Это вовсе несложно, если знать, как должна быть объявлена функция.
Шаг третий – отображаем код странички сайта средствами libcurl
Вследствие претворения в жизнь двух предыдущих шагов мы создали абсолютно все условия для работы с libcurl. Приступаем к самому интересному – заставим ее работать!
Итак, давай добьемся того, чтоб по указанному нами URL наша libcurl просто возвратила код страницы. Для этого в коде проекта ниже, после объявления функций easy-интерфейса, пишем следующий код:
Вызов html-кода странички сайта
//объявляем сессию
CURL *curl;//объявляем переменную для закачки html-кода
странички сайта
String table;
// инициализация сессии
curl = curl_easy_init();
if(curl) {// Задаем функцию вывода данных
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
Writer);
/
/ Записывает данные в //переменную
curl_easy_setopt(curl, CURLOPT_WRITEDATA,
&table);//Задаем URL
curl_easy_setopt(curl, CURLOPT_URL,
"http://www.xakep.ru/");// Отображаем заголовок (1- отобразить; 0 –
не отображать)
curl_easy_setopt(curl, CURLOPT_HEADER , 1 );//Исполняемая функция
curl_easy_perform(curl);//Уничтожает сессию и очищает память
curl_easy_cleanup(curl);
}Итак, полученная конструкция вернет html-код заглавной страницы сайта http://www.xakep.ru . Ответ будет закачан в переменную table. Но здесь я хочу обратить внимание на вставку функции curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,Writer). Давай с ней разберемся (http://curl.haxx.se/libcurl/c/curl_easy_setopt.html нам в помощь, ведь там расписан каждый параметр функции curl_easy_setopt). Остановим свой взгляд на цитате, которая входит в описание параметра CURLOPT_WRITEDATA.
Поскольку мы используем DLL в Win32, то здесь нам настоятельно рекомендуют включить функцию вывода данных. В нашем коде это осуществляется вставкой curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,Writer). Ну что ж, если надо – так сделаем:
Функция вывода данных
static size_t Writer(char *data, size_t size,
size_t nmemb, AnsiString *buffer)
{
size_t result = 0;
if(buffer != NULL)
{
buffer->Insert(data,buffer->Length()+1);
//заполняем переменную buffer
result = size * nmemb;
// формируем значение количества переданных
байт данных
}
return result;
}По описанию, число переданных в функцию байт через параметр char *data должно быть равно возвращаемому результату result (result = size * nmemb). Таким образом идет сверка этих чисел и, если они не совпадают, возникает ошибка, и передача данных прекращается. Передача данных в функцию осуществляется порциями, и эти порции аккумулируются в переменной buffer, все время добавляясь в конец. Добавим код этой функции в наш проект, затем - перетянем на форму текстовое поле и допишем в нашем обработчике события нажатия кнопки строчку Memo1->Text= table; сразу после вызова функции curl_easy_perform. Теперь откомпилируем проект и нажмем на кнопку - в текстовом поле Memo1 отобразится HTML-код запрашиваемой странички с заголовком.
Шаг четвертый – пополняем возможности
Мы уже разобрались практически со всей необходимой информацией по принципам работы с проектом libcurl в среде Builder C++ и свободно можем начать самостоятельное изучение, руководствуясь только описанием функций и их параметров, которое щедро предоставляют нам разработчики на официальном сайте.
Включим в запрос, который формирует libcurl, информацию о типе браузера и версии HTTP протокола. Для этого вставим в код нашего проекта строки:
Включим в запрос, который формирует libcurl, информацию о типе браузера и версии HTTP протокола. Для этого вставим в код нашего проекта строки:
Задаем тип и версию браузера; устанавливаем версию протокола в HTTP 1.1
// добавляет в заголовок запроса тип и версию браузера
curl_easy_setopt(curl, CURLOPT_USERAGENT,
"Mozilla/5.0 (Windows; U; Windows NT 5.1;
en-US; rv:1.8.1.1) Gecko/20061204
Firefox/2.0.0.1");//устанавливает версию протокола, использованного в запросе, в HTTP 1.1
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,
CURL_HTTP_VERSION_1_1);Отмечу, что месторасположение функций curl_easy_setopt должно быть до исполняющей функции curl_easy_perform (их взаимный порядок не имеет значения). Теперь давай поглядим на текст запроса, который формирует наш libcurl через снифер сетевого трафика (я, например, использую SmartSniff) – смотри рисунок.
Тут красуется заголовочный параметр версии браузера «User-Agent» и версия протокола «HTTP 1.1». Как видно, далее уже все совсем просто - мы читаем описание функций и параметров на официальном сайте проекта cURL и применяем их в своей программе.
Теперь давай прикажем нашей libcurl работать через HTTPS-соединение, используя http-прокси с авторизацией и, конечно же, не забудем про COOKIES. Добавляем следующий код в наш проект:
// задаем адрес http-прокси с номером порта и авторизуемся на нем
curl_easy_setopt(curl,CURLOPT_PROXY,"x.x.x.x:y
yyy");
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
"user:123");
// указываем имя файла для хранения и считывания cookies-файлов
curl_easy_setopt(curl, CURLOPT_COOKIEJAR,
"outfile.txt");
curl_easy_setopt ( curl, CURLOPT_COOKIEFILE,
"outfile.txt" );
// разрешаем работу через https-соединение
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER,
0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST,
0L);Как и в прежних примерах, имена параметров установочных функций отвечают сами за себя. Первый набор функций curl_easy_setopt, представленный выше в коде, задает IP-адрес прокси-сервера и его порт, тем самым разрешая возможность работы через прокси. Выполняет эта процедура вызов установочной функции curl_easy_setopt с параметром CURLOPT_PROXY. Адрес и порт прокси-сервера записаны знакомым форматом - через двоеточие. Установочная функция с параметром CURLOPT_PROXYUSERPWD устанавливает авторизацию на прокси-сервере, а логин и пароль задаются через двоеточие. Если необходимо использовать другие типы прокси, то дополнительно добавь в код установочную функцию curl_easy_setopt с параметром CURLOPT_PROXYTYPE; она принимает вторым параметром значение нужного типа прокси (по умолчанию используется HTTP-прокси).
Далее идет ряд установочных функций, каждая из которых разрешает работу с cookies. Здесь функция с параметром CURLOPT_COOKIEJAR принимает простое название файла, который будет автоматически создан в директории нашего проекта при вызове функции curl_easy_cleanup, и если сервер присылает в ответном заголовке cookies - то в указанный файл они все будут записаны в специальном формате. Функция с параметром CURLOPT_COOKIEFILE тоже принимает имя файла, но с которого, наоборот, будут считываться и загружаться значения cookies для созданной сессии libcurl. В промежутке одной сессии, при разрешенной работе с cookies, libcurl сама включает возможность автоматической работы с ними в своей памяти. Так, указав в обоих установочных функциях имя одного и того же файла, мы полностью автоматизируем работу с cookies в нашей программе. Следующий блок разрешает работу через HTTPS-соединение с некоторыми настройками. Эту роль здесь выполняют установочные функции с параметрами CURLOPT_SSL_VERIFYPEER и CURLOPT_SSL_VERIFYHOST, отвечающие, к тому же, за проверку подлинности сервера при сеансе связи. В нашем примере управляющие параметры этих функций установлены в 0, – проверка подлинности осуществляться не будет и соединение с сервером пройдет успешно в любом случае.
Если нужно создавать более информативные запросы к интернет-ресурсу путем добавления дополнительных заголовочных данных в формирующийся заголовок запроса, то воспользуемся установочной функцией с параметром CURLOPT_HTTPHEADER. Она принимает параметр типа struct curl_slist. Структура параметра типа struct curl_slist заполняется данными с помощью специальной функции curl_slist_append, а очищается функцией curl_slist_free_all (страничка с примером: http://curl.haxx.se/libcurl/c/curl_slist_append.html). Таким образом, можно полностью и с нуля самому вручную формировать запросы к серверу. Чтобы использовать эти функции в нашем проекте, их нужно объявить подобно easy-интерфейсу в шаге №2. Дополним нашу программу кодом:
Объявляем функции curl_slist_append и curl_slist_free_all
// объявление указателей на функции
struct curl_slist *(__stdcall
*curl_slist_append )
(struct curl_slist *list,const char *string);
void (__stdcall *curl_slist_free_all)(struct
curl_slist * list);//присваиваем указателям функций соответствующие адреса функции DLL
curl_slist_append=(curl_slist*(__stdcall *)
(struct curl_slist *list,const char
*string))GetProcAddress(cl,"curl_slist_append"
);
curl_slist_free_all=(void(__stdcall *)(struct
curl_slist *list))
GetProcAddress(cl,"curl_slist_free_all");Далее, руководствуясь описанием этих функций, думаю, тебе не составит труда реализовать их работу. В любом случае, на диске ты найдешь живой пример работы кучи функций библиотеки в демонстрационной программе с исходным кодом. Напоследок же рассмотрим, как можно отправить данные методом POST. Для этого мы используем установочную функцию с параметром CURLOPT_POST, с передаваемым в нее значением 1 - разрешить использование POST-запроса. Далее мы вызываем установочную функцию с параметром CURLOPT_POSTFIELDS и передаем в нее строку post-данных.
Разрешаем и формируем POST-запрос
// разрешаем использование POST -запроса
curl_easy_setopt(curl, CURLOPT_POST, 1);
// формируем POST-данные
curl_easy_setopt(curl, CURLOPT_POSTFIELDS,
"journal=Hacker ");Для передачи данных методом GET достаточно всего лишь добавить в конец URL вызываемой странички после символа «?» необходимые параметры, разделенные символом «&».
Комментариев нет:
Отправить комментарий