Рассмотрим библиотеку curl ее возможности, посмотрим как ее подключать и настраивать. Попытаюсь всеобще раскрыть данную тему, потому что она для меня очень важна, я собираюсь писать программы под веб, а с плохими знаниями этой библиотеки будет тяжело что нить сделать. Итак начнем.[tip] libcurl это свободная и простая в использовании клиентская библиотека по передачи данных по URL, она поддерживает DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET и TFTP. Также libcurl имеет поддержку SSL сертификатов, HTTP POST, HTTP PUT, FTP загрузку, HTTP form загрузку, proxy, cookies, user+password авторизацию (Basic, Digest, NTLM, Negotiate, Kerberos), докачивания файлов, http прокси туннелирования и многого другого.
libcurl легко переносима, она собирается и работает на многих платформах, включая Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HPUX, IRIX, AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, BeOs, Mac OS X, Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS и остальные…
libcurl свободна, потокобезопасна, совместима с IPv6, функциональна, имеет хорошую поддержку, быстрая, тщательно задокументирована и уже используется во многих известных, крупных и успешных компаний и в многочисленных приложениях. [/tip]
Содержание:
1. Установка библиотеки.
2. Основные принципы.
3. Простой пример.
4. Заголовки.
5. Обработка ошибок.
6. Загрузка в буфер.
7. Загрузка в файл.
8. Перенаправление (редирект).
9. Cookie
10. Преобразование в URL вид.
11. POST запрос для входа авторизации на сайте vk.com. (контакт)
12. Получение страниц в сжатом виде.
13. Передача с использованием https
Windows
1. Заходим на сайт http://curl.haxx.se/download.html и скачиваем версию библиотеки для виндовс Win32 — MSVC ftp://ftp.sunet.se/pub/www/utilities…2-ssl-msvc.zip .
[tip]Там я смотрел по ссылке той либы что раньше была уже нет, поэтому вот ссылка на старую либу которую я использую https://yadi.sk/d/Iu7nUbr4gzrto[/tip]
2. Распаковываем архив и берем оттуда все dll файлы:
- curllib.dll
- libeay32.dll
- openldap.dll
- ssleay32.dll
И папку curl ( там заголовойные файлы) находящуюся в папке .\libcurl-7.19.3-win32-ssl-msvc\include.
3. Так же берем curllib.lib из папки .\libcurl-7.19.3-win32-ssl-msvc\lib\Release.
Теперь для подключения curl нужно написать:
1 2 |
#include "curl/curl.h" #pragma comment(lib,"curllib.lib") |
Для работы программы также может понадобиться libsasl.dll ( из OpenSSL ). В таком случае при запуске программы из IDE она сразу же будет прекращать работу после без какой либо ошибки. Если же запустить сам exe файл то вылезит окошко указывающее на недостающую библиотеку. Требуемые dll несложно найти и скачать с интернета.
curl предоставляет несколько интерфейсов:
- Easy (Простой режим)
- Multi (Многопоточный режим)
- Share
При использовании в libcurl «простого» интерфейса вы инициализируете сеанс и получаете handle (часто упоминается как «easy handle»), который вы используете в качестве аргумента в функциях Easy интерфейса. Используйте curl_easy_init, чтобы получить handle.
После получения вы должны установить все нужные параметры в предстоящей передаче, наиболее важным среди которых является URL (передавать что-то без заданного URL невозможно). Вы можете задавать различные функции обратного вызова, которые будут вызываться из библиотеки, при получении данных и т.д. Для всего этого используется curl_easy_setopt.
Список опций можно найти в документации http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTURL
После того как все настройки окончены, вы сообщаете libcurl выполнение передачи с помощью curl_easy_perform. Она проделает все операции и вернет результат своей работы типа перечисления CURLcode.
После передачи, вы можете установить новые настройки и сделать еще передачу, или, если вы уже закончили, вызовите очистку сессии curl_easy_cleanup. Если вы хотите иметь постоянное подключение, не освобождайте handle сразу, вместо этого выполните другие передачи с использованием этого же handle.
Никогда не используйте один и тот же хендл в разных потоках! (можно сделать синхронизацию, но это сведёт на нет плюсы многопоточности)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#include <cstdio> //подключаем curl #include "curl/curl.h" #pragma comment(lib,"curllib.lib") int main() { CURL* curl;//объект CURLcode res;//сюда запишитса результат //легкая инициализация curl=curl_easy_init(); //если удалось инициализаровать объект if(curl) { //задаем url адресс curl_easy_setopt(curl,CURLOPT_URL,"http://www.kselax.ru"); //выполняем запрос res=curl_easy_perform(curl); //закрываем дескриптор curl curl_easy_cleanup(curl); } getchar(); return 0; } |
Этот код выводит в консоль содержимое html страницы.
Начитает easy(простую) сессию curll и возвращает ее дескриптор если не удачно установленный в NULL функция:
1 |
CURL *curl_easy_init(); |
Завершает работу сессии функция:
1 |
void curl_easy_cleanup(CURL * curl); |
Функция:
1 |
CURLcode curl_easy_setopt(CURL *curl, CURLoption option, parameter); |
Задает соответствующего поведение через установку опций, возвращает CURLE_OK (0) если успешно, в противном случае код ошибки определенный константами в файле curl/curl.h.
Опция CURLOPT_URL относится NETWORK-опциям и задает url- адрес. Этот параметр должен иметь вид согласно RFC 3986 формата: «scheme://host:port/path»
Функция:
1 |
CURLcode curl_easy_perform(CURL *curl); |
Выполняет отправку запроса на сервер и возвращает CURLE_OK в случае успеха, в противном случае код ошибки.
Заголовки запроса можно установить с помощью опций, но в зависимости от версии libcurl, константы определяющие опции могут отличатся.
1 2 3 4 5 |
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT,"Mozilla/5.0 (Windows NT 6.1; rv:16.0) Gecko/20100101 Firefox/16.0"); curl_easy_setopt(curl_handle, CURLOPT_ENCODING, "gzip,deflate"); // если curl скомпилина вместе с gzip // curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPALIVE , 1); // не нашло такой опции в версии 7.19.3 // curl_easy_setopt(curl_handle, CURLOPT_REFERER,"http://some.com"); // yстанавливает referer curl_easy_setopt(curl_handle, CURLOPT_AUTOREFERER,1);// автоматически заполняет поле referer |
Если установить
1 |
curl_easy_setopt(curl_handle, CURLOPT_HEADER, 1); |
то заголовки ответа http сервера будут отображаться вместе с телом ответа.
В случае возникновения ошибки при выполнении функции curl_easy_perform() можно получить ее описание с помощью:
1 |
const char *curl_easy_strerror(CURLcode errornum); |
Эта функция возвращает строку с описанием кода ошибки CURLcode указанным в аргументе:
1 2 3 |
CURLcode res = curl_easy_perform(curl_handle); if(res != CURLE_OK) printf( "curl_easy_perform() failed: %s\n", curl_easy_strerror(res) ); |
Так же есть возможность получить сообщение об ошибке из буфера ошибок, для этого нужно включить параметр CURLOPT_ERRORBUFFER с помощью ф-ции curl_easy_setopt() указать буфер.
1 2 3 4 5 6 7 |
static char ErrorBuffer[CURL_ERROR_SIZE]; // размер определяется константой curl //... curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, errorBuffer); // указывает буфер ошибок //... CURLcode res = curl_easy_perform(curl_handle); if(res != CURLE_OK) cout<<"Error!"<<ErrorBuffer<< endl; |
По умолчанию curl выводит данные в stdout то есть в окно консоли. Для того что бы сохранить данные в отдельном буфере нужно указать этот буфер в опции CURLOPT_WRITEDATA и callback функцию которая будет записывать туда данные при их приеме с помощью опции CURLOPT_WRITEFUNCTION.
Функция должна иметь вид:
1 |
size_t function( char *ptr, size_t size, size_t nmemb, void* userdata); |
char * ptr — указатель на принимаемые данные.
size_t size — размер принимамого блока данных
size_t nmemb — общее количество блоков данных.
void* userdata — это параметр опции CURLOPT_WRITEDATA, в который производится запись — наш буфер.
Функция должна возвращать количество обработанных байт (size* nmemb). Если это количество будет отличаться от суммы, полученной на входе вашей функции, то будет отдан сигнал об ошибке в библиотеке. Это можно использовать для прервания передачи, с возвращенным значением CURLE_WRITE_ERROR.
Функция может вернуть значение CURL_WRITEFUNC_PAUSE, которое приведет к приостановке записи в этом соединении.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
#include <cstdio> #include <cstdlib> using std::exit; #include <cstring> using std::strlen; #include <iostream> using std::cout; using std::endl; //подключаем curl #include "curl/curl.h" #pragma comment (lib,"curllib.lib") //создаем буфер const size_t BUF_SIZE=5000000; char wr_buf[BUF_SIZE];//массив указателей из 5 милионов указателей size_t wr_index=0;//переменная для индекса массива указателей (перебор указателей) //Функция которая будет заполнять буфер static size_t write_data(char* ptr, size_t size, size_t nmemb, char* data) { //Если выход за размеры буфера ошибка. if(data==NULL||/*wr_index+*/size*nmemb>BUF_SIZE)return 0; memcpy(&data[0],ptr,size*nmemb);//дописываем данные в конец wr_index+=size*nmemb;//изменяем текущее положение return size*nmemb; } int main() { CURL* curl; CURLcode res; memset(wr_buf,BUF_SIZE+1,0);//заполняем буфер нулями curl=curl_easy_init(); if(curl) { curl_easy_setopt(curl,CURLOPT_URL,"http://www.kselax.ru"); curl_easy_setopt(curl,CURLOPT_WRITEDATA,wr_buf); curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_data); res=curl_easy_perform(curl); if(res==CURLE_OK) { printf("%s\n Done!",wr_buf);//выводим буфер в консоль } else printf("curle easy_perform() failed: %s\n",curl_easy_strerror(res)); curl_easy_cleanup(curl); } getchar(); return 0; } |
В качестве буфера можно использовать контейнер или поток STL например std::string.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#include <string> using std::string; #include <iostream> using std::cout; using std::endl; //подключаем curl #include "curl/curl.h" #pragma comment(lib,"curllib.lib") //создаем функцию для записи static size_t my_fun(char* ptr,size_t size, size_t nmemb, string* str) { if(str) { //размещает в блоке памяти размером size*nmemb данные из ptr (видимо) str->append(ptr,size*nmemb); return size*nmemb; } else return 0;//ошибка } int main() { CURL* curl; CURLcode res; string content; curl=curl_easy_init(); if(curl) { curl_easy_setopt(curl,CURLOPT_URL,"http://www.kselax.ru"); curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,my_fun); curl_easy_setopt(curl,CURLOPT_WRITEDATA,&content); res=curl_easy_perform(curl); if(res==CURLE_OK)cout <<content<<"\nDone!"<<endl; else cout <<"curl_easy_perform failed: "<<curl_easy_strerror(res)<<endl; curl_easy_cleanup(curl); } getchar(); return 0; } |
Следующий пример показывает как можно сохранить тело ответа сервера в один файл, а заголовок в другой.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#include <cstdio> #include <cstdlib> //подключаем curl #include "curl/curl.h" #pragma comment(lib,"curllib.lib") //создаем функцию для записи size_t my_func(char* ptr, size_t size, size_t nmemb, FILE* data) { return fwrite(ptr,size,nmemb,data); } int main() { //Открываем файлы для заголовка и тела const char* head="head.txt"; const char* body="body.html"; FILE* headfile=fopen(head,"w"); if(headfile==NULL) return -1; FILE* bodyfile=fopen(body,"w"); if(bodyfile==NULL) return -1; //выполняем запрос CURL* curl=curl_easy_init(); if(curl) { curl_easy_setopt(curl,CURLOPT_URL,"http://www.kselax.ru"); curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,my_func); //записываем заголовок curl_easy_setopt(curl,CURLOPT_WRITEHEADER,headfile); //записываем тело curl_easy_setopt(curl,CURLOPT_WRITEDATA,bodyfile); //отправка запроса CURLcode res=curl_easy_perform(curl); if(res!=CURLE_OK) printf("curl_easy_perform() failed: %s \n",curl_easy_strerror(res)); curl_easy_cleanup(curl); } puts("\n Done!"); getchar(); return 0; } |
8. Перенаправление (редирект).
Для автоматического перехода на перенаправляемую страницу необходимо установить опцию CURLOPT_FOLLOWLOCATION в 1
1 |
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); |
Для того что бы ограничить количество перенаправлений нужно установить опцию CURLOPT_MAXREDIRS ее параметр указывает их максимальное количество
1 |
curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10); // останавливаться после 10-ого редиректа |
Далее описание опций для работы с cookie
CURLOPT_COOKIE
1 |
curl_easy_setopt(curl_handle, CURLOPT_COOKIE, cookiestring); |
Параметр -указатель на строку в стиле Си для установки cookies в http-запросе.Формат строки должен быть вида name=contents, где name имя cookie, а contents-ее содержание.
Используется, когда вы хотите указать точное содержание cookie-заголовка для отправки на сервер.
Если нужно передать несколько cookie, то строка должна выглядеть как «name1 = content1; name2 = content2;» и т.д.
CURLOPT_COOKIEFILE
1 |
curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, cookiefilename); |
Принимает указатель на строку в стиле Си, в которой храниться путь к файлу, который содержит cookies. Cookies должны храниться в формате куков Netscape/Mazilla или в обычном HTTP-стиле заголовков (Set-Cookie: …) помещенных в файл
Если указать несуществующий файл или пустую строку («»), то это разрешит libcurl полученные использовать cookie в следующих запросах для данного дескриптора curl.
Можно несколько раз устанавливать эту опцию для загрузки нескольких файлов с куками.
CURLOPT_COOKIEJAR
1 |
curl_easy_setopt(curl_handle, CURLOPT_COOKIEJAR, cookiefilename); |
Запишет все известные cookies в указанный файл. Если cookies нет файл не будет создан. Если указать «-» вместо имени файла cookies будут выведены в окно консоли (stdout), и будет разрешено использование cookies для этой сессии.
Если файл не может быть создан или сохранен libcurl не выдаст ошибку.Использование опций CURLOPT_VERBOSE или CURLOPT_DEBUGFUNCTION вызовет вывод предупреждения
CURLOPT_COOKIESESSION
1 |
curl_easy_setopt(curl_handle, CURLOPT_COOKIESESSION, 1); |
Установка в 1 укажет текущему сеансу начать новую «сессию» cookies. Это заставит libcurl проигнорировать все «сессионные» cookies, которые она должна была бы загрузить, полученные из предыдущих сессий. По умолчанию, libcurl всегда сохраняет и загружает все cookies, вне зависимости от того, являются ли они «сессионными» или нет. «Сессионные» cookies-это cookies без срока истечения, которые должны существовать только для текущей «сессии».
CURLOPT_COOKIELIST
1 |
curl_easy_setopt(curl_handle, CURLOPT_COOKIELIST, "ALL"); // Чистка cookies |
Устанавливает cookies.
Если задать параметр «ALL» то все cookies будут очищены, если «FLUSH» будут сохранены в файл указанный в опции CURLOPT_COOKIEJAR
Для вывода информации о cookie можно воспользоваться функцией из примера cookie_interface.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
//получает объект curl static void print_cookies(CURL *curl) { CURLcode res;//код для ошибки //непонятные структуры struct curl_slist *cookies; struct curl_slist *nc; int i; printf("Cookies, curl knows:\n"); res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);//получить инфо о куки if (res != CURLE_OK)//если не ок, то вывод ошибки { fprintf(stderr, "Curl curl_easy_getinfo failed: %s\n", curl_easy_strerror(res )); exit(1); } //вывод всех куки nc= cookies, i = 1; while (nc) { printf("[%d]: %s\n", i, nc->data); nc = nc->next;//переход к следующей куке i++; } if (i == 1) printf("(none)\n");//типо нету куки curl_slist_free_all(cookies);//эта функция видимо удаляет } |
Иногда возникает необходимость передавать GET/POST запросы параметры которые содержат в себе символы требующие «экранирования» (кириллица, символ @).К примеру необходимо выполнить поиск в яндексе по слову «Программирование», если посмотреть в строку браузера, то там это будет выглядеть так:
1 |
http://yandex.ua/yandsearch?text=Программирование |
Слово «Программирование» должно экранироваться при запроссе.
1 |
http://yandex.ua/yandsearch?text=%CF%F0%EE%E3%F0%E0%EC%EC%E8%F0%EE%E2%E0%ED%E8%E5 |
Для этих целей в curl предусмотрена функция.
1 |
char* curl_easy_escape( CURL* curl , char* url , int length ); |
Эта функция преобразует входную строку в закодированную для URL строку и возвращает ее в качестве новой выделенной строки. Все входные символы, кроме a-z, A-Z, 0-9 преобразуются в их «замаскированные» версии (%NN, где NN — двузначное шестнадцатеричное число).
Если длинна аргумента имеет значение 0 (ноль), curl_easy_escape() использует strlen() на входной строке чтобы вычислить размер.
Вы должны освободить полученную строку с помощью curl_free, после окончания работы с ней
1 |
void curl_free ( char* ptr ); |
curl_free освобождает память которая была была выделена внутри функции curl. Необходимо использовать curl_free() вместо free(), что бы избежать ошибок, которые могут возникнуть по причине возможных различий при управлении памятью в вашем приложении и curl.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
#include <cstdio> #include <cstdlib> #include <iostream> using std::cout; using std::endl; #include <string> using std::string; //подключаем curl #include "curl/curl.h" #pragma comment(lib,"curllib.lib") int main() { CURL* curl; CURLcode res; curl=curl_easy_init(); if(curl) { char ru_txt[]="Животные"; //преобразовываем русский текст char* esc_text=curl_easy_escape(curl,ru_txt,0); if(!esc_text)//если нул { cout <<"Can not convert string to URL"<<endl; curl_easy_cleanup(curl); getchar(); return 1; } string url="http://www.google.ru/#newwindow=1&q="; url+=esc_text; //освобождаем память curl_free(esc_text); //задаем url-адресс curl_easy_setopt(curl,CURLOPT_URL,url.c_str()); //разрешаем перенаправление curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1); //выполняем запрос res=curl_easy_perform(curl); curl_easy_cleanup(curl);//удаляем дескриптора } getchar(); return 0; } |
Для удобства использования c std::string можно написать такую функцию:
1 2 3 4 5 6 7 8 9 10 11 |
std::string escape(CURL *curl_handle, const std::string& text) { std::string result; char* esc_text= curl_easy_escape(curl_handle, text.c_str(), text.length()); if(!esc_text) throw std::runtime_error("Can not convert string to URL"); result = esc_text; curl_free(esc_text); return result; } |
11. POST запрос для входа авторизации на сайте vk.com. (контакт)
В качестве примера приведу авторизацию на vk.com с последующим переходом на страницу для поиска людей, для работы примера вам необходимо указать свой e-mail и пароль. Результат работы программы она копирует страницу поиска и создает файл text.html.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
#include <cstdio> #include <cstdlib> using std::exit; #include <string> using std::string; #include <iostream> using std::cout; using std::endl; using std::cin; using std::ostream; using std::runtime_error; //подключаем curl #include "curl/curl.h" #pragma comment(lib,"curllib.lib") //функция экранирования string escape(CURL* curl,const string& text) { string result; char* esc_text=curl_easy_escape(curl,text.c_str(),text.length()); if(!esc_text)throw runtime_error("Can not convert string to URL"); result=esc_text; curl_free(esc_text); return result; } static size_t write_data(char* ptr, size_t size, size_t nmemb, string* data) { if(data) { data->append(ptr,size*nmemb); return size*nmemb; } else return 0; } static size_t write_head(char* ptr, size_t size, size_t nmemb, ostream* stream) { (*stream)<< string(ptr, size*nmemb); return size*nmemb; } int main() { string content; /*Пользовательские данные*/ //string url_dologin="http://www.cyberforum.ru/login.php?do=login";//страница входа string url_dologin="http://login.vk.com/?act=login"; string user_name;//e-mail string password;//pass cout <<"email: "; getline(cin,user_name); cout <<"password: "; getline(cin,password); cout <<endl; string url_user="http://vk.com/search?c[name]=1&c[photo]=1&c[section]=people"; // Мой кабинет //инициализация curl CURL* curl=curl_easy_init(); if(curl) { //формирование запросса на основе пользовательских данных std::string post_data; post_data+= "vb_login_username=" + escape(curl, user_name); post_data+= "&cookieuser=1"; post_data+= "&vb_login_password=" + escape(curl, password); post_data+= "&s=&securitytoken=guest"; post_data+= "&do=login"; post_data+= "&vb_login_md5password="; post_data+= "&vb_login_md5password_utf="; post_data+="act=login"; post_data+="role=al_frame"; post_data+="expire="; post_data+="captcha_sid="; post_data+="captcha_key="; post_data+="_origin=http%3A%2F%2Fvk.com"; post_data+="ip_h="; post_data+="email="+escape(curl,user_name); post_data+="pass="+escape(curl,password); curl_easy_setopt(curl,CURLOPT_URL,url_dologin.c_str()); //сохроняем html код страницы в строку content curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_data); curl_easy_setopt(curl,CURLOPT_WRITEDATA,&content); //Заголовок ответа сервера выводим в консоль curl_easy_setopt(curl,CURLOPT_HEADERFUNCTION,write_head); curl_easy_setopt(curl,CURLOPT_WRITEHEADER,&cout); //автоперенаправление curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1); //max 5 перенаправлений curl_easy_setopt(curl,CURLOPT_MAXREDIRS,5); //разрешаем использовать cookie (разрешает куки использовать в текущем curl) curl_easy_setopt(curl,CURLOPT_COOKIEFILE,""); /* POST - запрос с авторизацией (происходит получение кукисов)*/ curl_easy_setopt(curl,CURLOPT_POSTFIELDS, post_data.c_str()); curl_easy_setopt(curl,CURLOPT_POSTFIELDSIZE,post_data.length()); CURLcode res=curl_easy_perform(curl); if(res!=CURLE_OK) { cout <<curl_easy_strerror(res)<<endl; getchar(); return 0; } // cout <<"dsfsdafsa"<<endl;exit(1); //Проверяем успешно ли авторизовались //if(content.find("Спасибо, что зашли")!=string::npos) if(content.size()!=0) { cout <<"Autentificated!"<<endl; } else { cout <<"Non-autentificated!"<<endl; curl_easy_cleanup(curl); getchar(); return 0; } /* Get- запросс для перехода в "Мой кабинет форума" */ content.clear();//очищаем строку //меняем post режим на get curl_easy_setopt(curl,CURLOPT_POST,0); curl_easy_setopt(curl,CURLOPT_HTTPGET,1); //меняем url curl_easy_setopt(curl,CURLOPT_URL,url_user.c_str()); //отправляем запрос res=curl_easy_perform(curl); if(res!=CURLE_OK) { cout <<curl_easy_strerror(res)<<endl; } //Проверяем получили то что ожидали if(content.size()!=0) { cout <<content<<endl; FILE* f=fopen("text.html","w"); fprintf(f,"%s",content.c_str()); fclose(f); cout <<"content.size()= "<<content.size()<<endl; cout <<"Done!"<<endl; } else { cout <<"Is not my cabinet page"<<endl; } curl_easy_cleanup(curl); } return 0; } |
Основные моменты:
1. Для успешной авторизации и перехода по страницам нужно:
- разрешить использовать полученные cookie;
- включить автоматический переход по перенаправлениям
2. По умолчанию libcurl использует GET режим отправки запросов, после установки опции CURLOPT_POSTFIELDSIZE он переключается на POST, поэтому для осуществления последующего GET нужно переключить режим на GET
1 2 |
curl_easy_setopt(curl_handle, CURLOPT_POST, 0); // выключаем POST curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1);// включаем GET |
3. Для анализа того что отправляет и принимает програмка удобно использовать снифер я вообще использую надстройку для фаерфокса, что бы посмотреть что отсылать.
12. Получение страниц в сжатом виде.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#include <string> #include <iostream> #include "curl/curl.h" #pragma comment(lib,"curllib.lib") // для VC++ //--------------------------------------------------------------------------- int main() { std::string url= "http://www.google.ru/"; CURL *curl_handle = curl_easy_init(); if(curl_handle) { curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str() ); curl_easy_setopt(curl_handle, CURLOPT_ENCODING, "gzip,deflate"); // Принудительно ставим gzip CURLcode res = curl_easy_perform(curl_handle); if(res != CURLE_OK) std::cout<<"Error #"<<res<<" "<<curl_easy_strerror(res) <<std::endl; curl_easy_cleanup(curl_handle); } std::cout<<std::endl<<"Done!"; getchar(); return 0; } |
13. Передача с использованием https
Для работы по протоколу HTTPS необходимо что бы libcurl была собрана с поддержкой SSL, а также необходимы соответствующие dll-ки (из OpenSSL)Если библиотека собрана без SSL, то функция curl_easy_perform() вернет код CURLE_UNSUPPORTED_PROTOCOL (1) «Unsupported protocol»
Далее пример простого https— запроса :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
#include <cstdio> #include <cstdlib> #include <string> using std::string; #include <iostream> using std::cout; using std::endl; #include "curl/curl.h" #pragma comment(lib,"curllib.lib") size_t write_data(char* ptr, size_t size, size_t nmemb, FILE* data) { return fwrite(ptr,size,nmemb,data); } int main() { //Открываем файлы для заголовка и тела string body_filename="body.html"; FILE* body_file=fopen(body_filename.c_str(),"w"); if(body_file==NULL)return -1; string url="https://my.webmoney.ru/login.aspx"; CURL* curl=curl_easy_init(); if(curl) { //сохранение в файл html-страницу curl_easy_setopt(curl,CURLOPT_WRITEDATA,body_file); curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_data); //заголовки ответа выводим в консоль curl_easy_setopt(curl,CURLOPT_WRITEHEADER,stdout); //https - запрос curl_easy_setopt(curl,CURLOPT_URL,url.c_str()); //не проверять ssl - сертификат curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0); //не проверять хост ssl - сертификата curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,0); //отправляем запрос CURLcode res=curl_easy_perform(curl); if(res!=CURLE_OK) cout <<"error "<<res<<' '<<curl_easy_strerror(res)<<'\n'; else cout <<"Done!"<<endl; //закрываем curl curl_easy_cleanup(curl); } getchar(); return 0; } /* #include <stdio.h> #include <stdlib.h> #include <string> #include <iostream> #include "curl/curl.h" //#pragma comment(lib,"curllib-bcb.lib") // Для C++Builder #pragma comment(lib,"curllib.lib") // для VC++ //--------------------------------------------------------------------------- size_t write_data( char *ptr, size_t size, size_t nmemb, FILE* data) { return fwrite(ptr, size, nmemb, data); } //--------------------------------------------------------------------------- int main() { // Открываем файлы для заголовка и тела std::string body_filename = "body.html"; FILE *body_file = fopen(body_filename.c_str(),"w"); if (body_file == NULL) return -1; std::string url= "https://my.webmoney.ru/login.aspx"; CURL *curl_handle = curl_easy_init(); if(curl_handle) { // сохранение в файл html-страницу curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, body_file); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data); // заголовки ответа выводим в консоль curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, stdout); /* HTTPs Запрос curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str() ); // не проверять SSL сертификат curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); // не проверять Host SSL сертификата curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0); CURLcode res = curl_easy_perform(curl_handle); if(res != CURLE_OK) std::cout<<"Error #"<<res<<" "<<curl_easy_strerror(res) <<std::endl; curl_easy_cleanup(curl_handle); } std::cout<<std::endl<<"Done!"; getchar(); return 0; }*/ |
Разультат запроса будет сохранен в файле body.html, заголовок ответа сервера будет выведен на экран.
1. Установка библиотеки.
2. Основные принципы.
3. Простой пример.
4. Заголовки.
5. Обработка ошибок.
6. Загрузка в буфер.
7. Загрузка в файл.
8. Перенаправление (редирект).
9. Cookie
10. Преобразование в URL вид.
11. POST запрос для входа авторизации на сайте vk.com. (контакт)
12. Получение страниц в сжатом виде.
13. Передача с использованием https
[youtube]https://www.youtube.com/watch?v=IZnkiJqZwOs[/youtube]
А что значит «2. Распаковываем архив и берем оттуда все dll файлы:» берём, а потом куда их скопировать надо?
там dll-ки их все что в папке есть нужно скопировать в папку проекта — ту папку где находится исходные файлы, а потом когда создашь программу нужно копировать их в папку где будет находится исполняемый файл.
Контент статьи ворованный:
http://www.cyberforum.ru/blogs/131347/blog1151.html
Да ты мне еще на форуме помогал по curl, что то не получалось не помню, потом решил свою статью из твоей переделать, я чуток код поменял 🙂