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, функциональна, имеет хорошую поддержку, быстрая, тщательно задокументирована и уже используется во многих известных, крупных и успешных компаний и в многочисленных приложениях.[ 2]
| Содержание
1. Установка библиотеки.
2. Основные принципы.
3. Простой пример.
4. Заголовки.
5. Обработка ошибок.
6. Загрузка в буфер
7. Загрузка в файл.
8. Перенаправление (редерикт).
9. Cookie.
10. Преобразование в URL вид.
11. POST-запрос для авторизации на форуме.
12. Получение страниц в сжатом виде.
13. Передача с использованием HTTPs (расширение протокола HTTP, поддерживающее шифрование).
Исходники.
Литература.
Темы.
1 Установка библиотеки
Ubuntu Linux
Достаточно стандартно выполнить команду
| Bash | 1
| sudo apt-get install curl libcurl3 libcurl3-dev |
|
В дальнейшем собирать исходники надо с опцией -lcurl, например
| Bash | 1
| g++ main.o -o prog -lcurl |
|
Windows
1. Заходим на сайт http://curl.haxx.se/download.html. Качаем версию библиотеки для Win32 - MSVC http://curl.haxx.se/download/l... l-msvc.zip
2. Распаковываем архив берем от туда все dll- файлы:- curllib.dll ;
- libeay32.dll ;
- openldap.dll ;
- ssleay32.dll .
И папку curl ( там заголовойные файлы) находящуюся в папке .\libcurl-7.19.3-win32-ssl-msvc\include
Примечание:
На данный момент ссылки стали нерабочими, нужно качать исходники и собирать самому из исходников в MSVC. Но если влом - используйте библиотеки что в примерах (в архиве прикреплены).
3. Так же берем curllib.lib из папки .\libcurl-7.19.3-win32-ssl-msvc\lib\Release
Если у вас MSVC++ используем его, если С++Builder конвертируем файл curllib.lib в curllib-bcb.lib утилитой coff2omf.exe
| Code | 1
| coff2omf curllib.lib curllib-bcb.lib |
|
Теперь для подключения curl нужно написать
| C++ | 1
2
3
| #include "curl/curl.h"
#pragma comment(lib,"curllib.lib") // для MSVC++
// #pragma comment(lib,"curllib-bcb.lib") // для C++Builder |
|
Для работы программы также может понадобиться libsasl.dll ( из OpenSSL ) и возможно какие-нибудь библиотеки из MSVC++(Если у вас C++Builder).В таком случае при запуске программы из IDE она сразу же будет прекращать работу после без какой либо ошибки. Если же запустить сам exe файл то вылезит окошко указывающее на недостающую библиотеку. Требуемые dll несложно найти и скачать с интернета.
2. Основные принципы
cUrl предоставляет несколько интерфейсов:- Easy (Простой режим)
- Multi (Многопоточный режим)
- Share
При использовании в libcurl "простого" интерфейса вы инициализируете сеанс и получаете handle (часто упоминается как "easy handle"), который вы используете в качестве аргумента в функциях Easy интерфейса. Используйте curl_easy_init, чтобы получить handle.
После получения вы должны установить все нужные параметры в предстоящей передаче, наиболее важным среди которых является URL (передавать что-то без заданного URL невозможно). Вы можете задавать различные функции обратного вызова, которые будут вызываться из библиотеки, при получении данных и т.д. Для всего этого используется curl_easy_setopt.[ 2]
| Список опций можно найти в документации [1]
После того как все настройки окончены, вы сообщаете libcurl выполнение передачи с помощью curl_easy_perform. Она проделает все операции и вернет результат своей работы типа перечисления CURLcode.
После передачи, вы можете установить новые настройки и сделать еще передачу, или, если вы уже закончили, вызовите очистку сессии curl_easy_cleanup. Если вы хотите иметь постоянное подключение, не освобождайте handle сразу, вместо этого выполните другие передачи с использованием этого же handle.
Никогда не используйте один и тот же хендл в разных потоках! (можно сделать синхронизацию, но это сведёт на нет плюсы многопоточности)[ 2]
|
3. Простой пример
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| #include <stdio.h>
#include "curl/curl.h"
#pragma comment(lib,"curllib-bcb.lib") // Для C++Builder
//#pragma comment(lib,"curllib.lib") // для VC++
//---------------------------------------------------------------------------
int main()
{
CURL * curl_handle = curl_easy_init();
if(curl_handle)
{
// задаем url адрес
curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.cyberforum.ru");
// выполняем запрос
CURLcode res = curl_easy_perform(curl_handle);
// закрываем дескриптор curl
curl_easy_cleanup(curl_handle);
}
getchar();
return 0;
}
//--------------------------------------------------------------------------- |
|
В итоге в окне консоли получаем html-код страницы форума.
| C++ | 1
| CURL *curl_easy_init(); |
|
Начинает easy(простую) curl-сессию, возвращает её дескриптор, в случае неудачи NULL.
Каждому вызову такой ф-ции должен соответствовать вызов ф-ции
| C++ | 1
| void curl_easy_cleanup(CURL * curl); |
|
для завершении работы.
| C++ | 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" (смотри также Преобразование в URL вид.)
| C++ | 1
| CURLcode curl_easy_perform(CURL *curl); |
|
Выполняет отправку запроса на сервер и возвращает CURLE_OK в случае успеха, в противном случае код ошибки. [1]
4. Заголовки.
Заголовки запроса можно также установить с помощью опций, но в зависимости от версии libcurl, константы определяющие опции могут отличаться.
| C++ | 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 |
|
Если установить
| C++ | 1
| curl_easy_setopt(curl_handle, CURLOPT_HEADER, 1); |
|
то заголовки ответа сервера будут отображаться в месте с html-кодом страницы (заголовок + тело)
5. Обработка ошибок.
В случае возникновения ошибки при выполнении функции curl_easy_perform() можно получить её описание с помощью:
| C++ | 1
| const char *curl_easy_strerror(CURLcode errornum); |
|
Эта функция возвращает строку с описанием кода ошибки CURLcode указанным в аргументе:
| C++ | 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() указать буфер.
| C++ | 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; |
|
6. Загрузка в буфер.
По умолчанию curl выводит данные в stdout т.е. в окно консоли. Для того что бы сохранить данные в отдельном буфере нужно указать этот буфер в опции CURLOPT_WRITEDATA и callback функцию которая будет записывать туда данные при их приёме с помощью опции CURLOPT_WRITEFUNCTION.
Функция должна иметь вид:
| C++ | 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, которое приведет к приостановке записи в этом соединении.
В качестве буфера можно использовать контейнер или поток STL что упростит задачу.
Для примера использование std::string :
| 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
31
32
33
34
35
36
37
38
39
40
41
42
43
| //----------------------------------------------------------------------------
#include <string>
#include <iostream>
#include "curl/curl.h"
#pragma comment(lib,"curllib-bcb.lib") // Для C++Builder
//#pragma comment(lib,"curllib.lib") // для VC++
//----------------------------------------------------------------------------
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; // будет ошибка
}
//-----------------------------------------------------------------------------
int main()
{
CURL *curl_handle;
curl_handle = curl_easy_init();
if (curl_handle)
{
curl_easy_setopt(curl_handle, CURLOPT_URL, "google.com");
std::string content;
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &content);
CURLcode res = curl_easy_perform(curl_handle);
if (res) std::cout << content << std::endl;
else std::cerr << curl_easy_strerror(res) << std::endl;
curl_easy_cleanup(curl_handle);
}
getchar();
return 0;
}
//----------------------------------------------------------------------------- |
|
7. Загрузка в файл
Следующий пример показывает как можно сохранить тело ответа сервера в один в файл, а заголовок в другой.
| 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| #include <string>
#include <iostream>
#include "curl/curl.h"
#pragma comment(lib,"curllib-bcb.lib")
//---------------------------------------------------------------------------
size_t write_data( char *ptr, size_t size, size_t nmemb, FILE* data)
{
return fwrite(ptr, size, nmemb, data);
}
//---------------------------------------------------------------------------
int main()
{
// Открываем файлы для заголовка и тела
const std::string header_filename= "head.txt";
const std::string body_filename = "body.html";
FILE *header_file= fopen(header_filename.c_str(),"w");
if (header_file == NULL)
return -1;
FILE *body_file = fopen(body_filename.c_str(),"w");
if (body_file == NULL)
return -1;
// Выполняем запрос
CURL *curl_handle = curl_easy_init();
if(curl_handle)
{
const std::string url= "https://www.cyberforum.ru";
curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
// сохраняем тело
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, header_file);
CURLcode res = curl_easy_perform(curl_handle);
if(res != CURLE_OK)
std::cout<< "curl_easy_perform() failed: %s\n" << curl_easy_strerror(res) std::endl;
curl_easy_cleanup(curl_handle);
}
std::cout<< "\nDone!"<<std::endl;
getchar();
return 0;
}
//-------------------------------------------------------------------------- |
|
8. Перенаправление ( редирикт ).
Для автоматического перехода на перенаправляемую страницу необходимо установить опцию CURLOPT_FOLLOWLOCATION в 1
| C++ | 1
| curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); |
|
Для того что бы ограничить количество перенаправлений нужно установить опцию CURLOPT_MAXREDIRS
её параметр указывает их максимальное количество
| C++ | 1
| curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10); // останавливаться после 10-ого редиректа |
|
9. Cookie
Далее описание опций для работы с Cookie
CURLOPT_COOKIE
| C++ | 1
| curl_easy_setopt(curl_handle, CURLOPT_COOKIE, cookiestring); |
|
Параметр -указатель на строку в стиле Си для установки cookies в http-запросе .
Формат строки должен быть вида name=contents, где name имя cookie, а contents- её содержание.
Используется, когда вы хотите указать точное содержание cookie-заголовоков для отправки на сервер.
Если нужно передать несколько cookie, то строка должна выглядеть как "name1 = content1; name2 = content2;" и т. д.
CURLOPT_COOKIEFILE
| C++ | 1
| curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, cookiefilename); |
|
Принимает указатель на строку в стиле Си, которой хранится путь к файлу, который содержит cookies.
Сookies должны хранится в формате куков Netscape/Mozilla или в обычном HTTP-стиле заголовков (Set-Cookie: ...) помещенных в файл.
Если указать несуществующий файл или пустую строку (""), то это разрешит libcurl полученные использовать cookie в следующих запросах для данного дескриптора curl
Можно несколько раз устанавливать эту опцию для загрузки нескольких файлов с куками.
CURLOPT_COOKIEJAR
| C++ | 1
| curl_easy_setopt(curl_handle, CURLOPT_COOKIEJAR, cookiefilename); |
|
Запишет все известные cookies в указанный файл. Если cookies нет файл не будет создан. Если указать "-" вместо имени файла cookies будут выведены в окно консоли ( stdout ), и будет разрешено использование cookies для этой сессии
Если файл не может быть создан или сохранен libcurl не выдаст ошибку.
Использование опций CURLOPT_VERBOSE или CURLOPT_DEBUGFUNCTION вызовет вывод предупреждения.
CURLOPT_COOKIESESSION
| C++ | 1
| curl_easy_setopt(curl_handle, CURLOPT_COOKIESESSION, 1); |
|
Установка в 1 укажет текущему сеансу начать новую "сессию" cookies. Это заставит libcurl проигнорировать все "сессионные" cookies, которые она должна была бы загрузить, полученные из предыдущей сессии. По умолчанию, libcurl всегда сохраняет и загружает все cookies, вне зависимости от того, являются ли они "сессионными" или нет. "Сессионные" cookies - это cookies без срока истечения, которые должны существовать только для текущей "сессии".
CURLOPT_COOKIELIST
| C++ | 1
| curl_easy_setopt(curl_handle, CURLOPT_COOKIELIST, "ALL"); // Чистка cookies |
|
Устанавливает cookies.
Если задать параметр "ALL" то все cookies будут очищены , если "FLUSH" будут сохранены в файл указанный в опции CURLOPT_COOKIEJAR
Для вывода информации о cookie можно воспользоваться функцией из примера cookie_interface.c
| 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
| 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);
} |
|
10. Преобразование в URL вид.
Иногда возникает необходимость передавать GET/POST запросы параметры которые содержать в себе символы требующие "экранирования" ( кириллица, символ "@" ).
К примеру необходимо выполнить поиск в яндексе по слову "Программирование", если посмотреть в строку браузера, то там это будет выглядеть так:
| HTML5 | 1
| http://yandex.ua/yandsearch?text=Программирование |
|
Слово "Программирование" должно экранироваться при запросе:
| HTML5 | 1
| http://yandex.ua/yandsearch?text=%CF%F0%EE%E3%F0%E0%EC%EC%E8%F0%EE%E2%E0%ED%E8%E5 |
|
Для этих целей в curl предусмотрена функция
| C++ | 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, после окончания работы с ней.[ 2]
|
| C++ | 1
| void curl_free ( char* ptr ); |
|
curl_free освобождает память, которая была выделена внутри функций curl. Необходимо использовать curl_free() вместо free(), чтобы избежать ошибок, которые могут возникнуть по причине возможных различий при управлении памятью в вашем приложении и curl.[ 2]
|
Код для рассматриваемого примера
| 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| //---------------------------------------------------------------------------
#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++
//---------------------------------------------------------------------------
int main()
{
CURL *curl_handle;
CURLcode res;
curl_handle = curl_easy_init();
if(curl)
{
char ru_text[]= "Программирование";
// Преобразование в URL- вид
char* esc_text= curl_easy_escape( curl_handle, ru_text, 0);
if(!esc_text)
{
std::cout<<"can not convert string to URL" <<std::endl;
curl_easy_cleanup(curl_handle);
getchar();
return 1;
}
std::string url= "http://yandex.ua/yandsearch?text=";
url+= esc_text;
curl_free(esc_text);
// задаем url адрес
curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str() );
// разрешаем перенаправление
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
// выполняем запрос
res = curl_easy_perform(curl_handle);
curl_easy_cleanup(curl_handle);
}
getchar();
return 0;
}
//-------------------------------------------------------------------------- |
|
Для удобства использования с std::string можно написать такую функцию
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
| //---------------------------------------------------------------------------
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-запрос для авторизации на форуме.
В качестве примера приведу авторизацию на cyberforum.ru с последующим переходом в "Мой кабинет", для работы примера вам необходимо указать свой e-mail и пароль.
Результат выполнения программы приведен на рисунке справа.

| 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
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
| #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++
//---------------------------------------------------------------------------
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;
}
//----------------------------------------------------------------------------
static size_t write_data(char *ptr, size_t size, size_t nmemb, std::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, std::ostream* stream)
{
(*stream)<< std::string(ptr, size*nmemb);
return size*nmemb;
}
//---------------------------------------------------------------------------
int main()
{
/* Пользовательские данные */
const std::string url_dologin= "https://www.cyberforum.ru/login.php?do=login";// страница авторизации
const std::string url_user= "https://www.cyberforum.ru/usercp.php"; // Мой кабинет
std::string user_name; // e-mail
std::string password; // пароль
std::cout<<"e-mail: ";
getline(std::cin,user_name);
std::cout<<password<<"password: ";
getline(std::cin,password);
std::cout<<std::endl;
CURL *curl_handle = curl_easy_init();
if(curl_handle)
{
/* Формирование запроса на основе пользовательских данных */
std::string post_data;
post_data+= "vb_login_username=" + escape(curl_handle, user_name);
post_data+= "&cookieuser=1";
post_data+= "&vb_login_password=" + escape(curl_handle, password);
post_data+= "&s=&securitytoken=guest";
post_data+= "&do=login";
post_data+= "&vb_login_md5password=";
post_data+= "&vb_login_md5password_utf=";
curl_easy_setopt(curl_handle, CURLOPT_URL, url_dologin.c_str() );
// сохраняем html код cтраницы в строку content
std::string content;
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &content);
// Загловок ответа сервера выводим в консоль
curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, write_head);
curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, &std::cout);
// авто перенаправление
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
// max 5-ть перенаправлений
curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 5);
// разрешаем использовать куки
curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE,"");
/* POST- запрос c авторизацией ( происходит получение кукисов ) */
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, post_data.c_str() );
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, post_data.length() );
CURLcode res = curl_easy_perform(curl_handle);
if(res != CURLE_OK)
{
std::cout<< curl_easy_strerror(res) << std::endl;
getchar();
return 0;
}
// Проверяем успешно ли авторизировались
if( content.find("Спасибо, что зашли") != std::string::npos )
std::cout << "Authenticated!" <<std::endl<<std::endl;
else
{
std::cout<< "Non-Authenticated!" <<std::endl;
curl_easy_cleanup(curl_handle);
getchar();
return 0;
}
/* GET- запрос для перехода в "Мой кабинет" форума */
content.clear();
// меняем POST-режим на GET
curl_easy_setopt(curl_handle, CURLOPT_POST, 0);
curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1);
// меняем url
curl_easy_setopt(curl_handle, CURLOPT_URL, url_user.c_str() );
res = curl_easy_perform(curl_handle);
if(res != CURLE_OK) std::cout<< curl_easy_strerror(res) <<std::endl;
// Проверяем получили то что ожидали
if( content.find("Мой кабинет") != std::string::npos)
std::cout << ""My cabinet" downloaded." <<std::endl
<< "------------- Content -----------------" <<std::endl
<< content <<std::endl;
else std::cout << "Is not "My cabinet" page" <<std::endl;
curl_easy_cleanup(curl_handle);
}
getchar();
return 0;
}
//-------------------------------------------------------------------------- |
|
Основные моменты:
1. Для успешной авторизации и перехода по страницам нужно:- разрешить использовать полученные cookie;
- включить автоматический переход по перенаправлениям.
2. По умолчанию libcurl использует GET "режим" отправки запросов, после установки опции CURLOPT_POSTFIELDSIZE он переключается на POST, поэтому для осуществление последующего GET нужно переключить режим на GET:
| C++ | 1
2
| curl_easy_setopt(curl_handle, CURLOPT_POST, 0); // выключаем POST
curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1);// включаем GET |
|
3. Для анализа того что отправляет/принимает ваше приложение удобно использовать снифер. Я пользуюсь к примеру HTTP Analyzer V5.
  
12. Получение страниц в сжатом виде.
| 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
| //---------------------------------------------------------------------------
#include <string>
#include <iostream>
#include "curl/curl.h"
#pragma comment(lib,"curllib-bcb.lib") // Для C++Builder
//#pragma comment(lib,"curllib.lib") // для VC++
//---------------------------------------------------------------------------
int main()
{
const 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- запроса :
| 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
| //---------------------------------------------------------------------------
#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)
{
// сохранение в файл 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, 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, заголовок ответа сервера будет выведен на экран.
PDF вариант статьи:
Статья о curl.pdf (Прикреплено по просьбе пользователя reef213, составлял pdf тоже он cUrl в Dev C++)
Исходники:
HTTP, POST, авторизация на cyberforum (curl v7.19.3-ssl, C++Builder XE3).rar
HTTP, GET, (curl v7.22.0, g++ 4.6.3, Makefile, Ubuntu x32).rar
HTTP, POST, авторизация на cyberforum(curl v7.22.0, Qt5, Ubuntu x32).zip
Литература:
1. http://curl.haxx.se/
2. http://ru.libcurl.wikia.com/wi... 0%BA%D0%B8
3. cURL | System Development
Блоги :
Подключение Curl библиотеки. QtCreator, MinGW32, Windows
Темы :
1. Скачивание из интернета
2. Builder и curl
3. Замена строки
4. Опять кодировки
5. Работа с CURL
6. Curl без ssl или статическая линковка
7. Curl с нуля
|