Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > C/C++ Сетевое программирование
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 15.08.2009, 22:33   #1
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
Хорошо Работаем в сети с помощью libcurl

В этой статье я бы хотел осветить вопросы взаимодействия с Web и Ftp серверами в C++ программе.
Никто не запрещает программировать сокеты и самостоятельно реализовывать протоколы. Но зачем изобретать велосипед, когда существует готовое, отлаженное и мощное решение, способное удовлетворить практически любые Ваши потребности? Речь идет о библиотеке libcurl. Это простая в использовании, кроссплатформенная (поддерживаются Linux, Windows, Solaris, Qnx, FreeBSD, OpenBsd, MacOS X и многие другие) клиентская библиотека, позволяющая работать с протоколами FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS and FILE. Поддерживаются SSL сертефикаты, HTTP POST, HTTP PUT, FTP закачка, HTTP закачка, прокси-сервера, куки, аутентификация, восстановление закачки файла, тунелирование http proxy и многое другое. Libcurl имеет завязки на множество языков программирования, среди которых: C, C++, Java, Lisp, PHP, Ruby, Perl, Pascal, Haskell.
И самое главное - библиотека полностью свободна, как для некоммерческого, так и для коммерческого применения.
Разумеется, перед тем, как начать использование библиотеку - ее нужно получить, установить и дать возможность, своему компилятору, использовать ее. Рассмотрим выполнение этих действий, как обычно на примере двух платформ: Linux и Windows.

В случае Linux - все довольно просто, Вам необходимо скачать http://curl.haxx.se/download/curl-7.16.2.zip
В этом архиве содержиться полный исходный код библиотеки, скрипты сборки, а так же полная документация API и примеры (поэтому пользователям Windows так же не помешает скачать себе этот архив)
После распаковки - необходимо выполнить стандартную процедуру компиляции и установки, с помощью configure и make && make install. Это все, можно пользоваться возможностями библиотеки.
Для компиляции программы, следуюет добавлять к опциям компилятора
Код:
pkg-config --libs libcurl
pkg-config --cflags libcurl
либо
Код:
curl-config --libs libcurl 
curl-config --cflags libcurl
В случае Windows - немного сложнее.
Вам необходимо скачать http://my.guardpuppy.com/libcurl-7.1...zlib-1.2.3.zip
Распаковать следующие файлы в указанные места:
libcurl.dll - распаковать в %SystemDrive%\%SystemRoot%\System32
libeay32.dll - распаковать в %SystemDrive%\%SystemRoot%\System32
ssleay32.dll - распаковать в %SystemDrive%\%SystemRoot%\System32
zlib1.dll - распаковать в %SystemDrive%\%SystemRoot%\System32
Если Вы используете Visual Studio 98, то libcurl_imp.lib распаковать в %SystemDrive%\Program Files\Microsoft Visual Studio\VC98\Lib
Если Вы используете VisualStudio 2005 и новее, то libcurl_imp.lib распаковать в %SystemDrive%\Program Files\Microsoft Visual Studio 9.0\VC\lib
Распаковать содержимое каталога include полность:
Если Вы используете Visual Studio 98, то распаковать в %SystemDrive%\Program Files\Microsoft Visual Studio\VC98\Include
Если Вы используете VisualStudio 2005 и новее, то libcurl_imp.lib распаковать в %SystemDrive%\Program Files\Microsoft Visual Studio 9.0\VC\Include
Следует обратить внимание, что перед компиляцией проекта, во всех версиях Visual Studio, необходимо зайти в параметры проекта, перейти в раздел опций линковщика (linking), выбрать из выпадающего списка группу input и в появившийся список подключаемых, при компиляции, библиотек добавить, в самом конце, libcurl_imp.lib
Так же в архиве содержится консольная утилита curl.exe, позволяющая использовать все возможности библиотеки, в командном режиме.

Теперь все готово и можно приступать к рассмотрению библиотеки и написанию кода.

Последний раз редактировалось oleg kutkov; 15.08.2009 в 22:52.
oleg kutkov вне форума Ответить с цитированием
Старый 15.08.2009, 22:34   #2
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Libcurl имеет два режима работы: так называемый простой интерфейс (The Easy interface) и многопоточный интерфейс (The multi interface).
Для использования библиотеки необходимо подключить заголовочный файл curl.h
Код:
#include <curl/curl.h>
Доступ к функциям библиотеки осущствляеются после открытия новой easy сессии и получения управляющего интерфейса типа CURL. Без открытия сессии - вызывать какие либо фукнции запрещено. Для выполнения всех этих действий служит функция curl_easy_init(), она выполняет инициализацию библиотеки, открытие сессии и возвращает объект типа CURL или же NULL, в случае, когда что-то пошло не так.
Код:
CURL *curl; //объект типа CURL 
curl = curl_easy_init(); //инициализация
if(curl) //обязательная проверка
{
	//выполнение всех дальнейших действий с библиотекой
}
Далее необходимо задать опции сессии, такие как URL, с которым мы собираемся работать, прокси сервер (если он есть), функции обратного вызова (о них ниже) и т.п.
Задание опций осуществляется с помощью функции curl_easy_setopt.
Рассмотрим ее объявление и параметры:
Код:
CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
CURL *handle - указатель на интерфейс, который мы получили выше.
CURLoption option - название опции, которую следует задать.
parameter - параметр, который связывается с опцией, это может быть число, указатель на функцию, строка. Функцию можно вызывать несколько раз подряд, задавая необходимые опции. Все опции, по умолчанию, выключены.

Рассмотрим наиболее интересные и используемые опции, а так же их параметры.
CURLOPT_HEADER - применяется при работе с HTTP, ненулевое значение параметра заставляет библиотеку отображать заголовок в теле запрошенной страницы.
CURLOPT_WRITEFUNCTION - данная опция позволяет задавать, в качестве параметра, указатель на функцию обратного вызова. Эта функция вызывается библиотекой, каждый раз, когда принимаются какие либо данные, требующие дальнейшего использования или сохранения. Описание функции будеит преведено ниже.
CURLOPT_WRITEDATA - эта опция определяет параметр, как объект, в который производится запись принимаемых данных.
CURLOPT_READFUNCTION - опция полностью аналогичная CURLOPT_WRITEFUNCTION, но используетс для передачи данных удаленному узлу.
CURLOPT_READDATA - аналогично CURLOPT_WRITEDATA, но так же для передачи.
CURLOPT_ERRORBUFFER - опция определяет строковый параметр, в который будут записываться сообщения об ошибках в читабельном, для людей, виде.
CURLOPT_URL - очень важная опция, в параметре указывается строка - URL, с которым собираемся взаимодействовать. В строке параметра можно указать небходимый протокол, в виде стандартного префикса "http://" или "ftp://".
CURLOPT_PROXY - опция, определяет строковый параметр - адрес и порт прокси-сервера. Параметр имеет стандартный вид: айпи-адрес (или имя, если есть возможность это имя разрешить) сервера и через двоеточние порт. Например: "proxy:8080"
CURLOPT_PROXYTYPE - параметр этой опции задает тип прокси. Возможные значения параметра: CURLPROXY_HTTP, CURLPROXY_SOCKS4, CURLPROXY_SOCKS5
CURLOPT_HTTPPROXYTUNNEL - ненулевое значение параметра этой опции включает туннелирование вышеуказанного прокси.
CURLOPT_INTERFACE - строковый параметр этой опции задает внешний интерфейс, это может быть как айпи-адрес, так и имя. Разумеется, если сетевой интерфейс - единственный, эту опцию
CURLOPT_PORT
- эта опция позволяет задать номер порта удаленного узла. Если эта опция не задается, для соеинения используется порт по умолчанию, для протокола (http - 80, ftp - 21 и т.д.).
CURLOPT_PROXYUSERPWD - эта опция используется для аутентификации на прокси-сервере. Параметр передается в виде строки "логин:пароль".
CURLOPT_USERPWD - опция используется для HTTP аутентификации. Параметр аналогичен предидущему.
CURLOPT_HTTPAUTH - параметр этой опции определяет тип HTTP аутентификации, возможные значения:
CURLAUTH_BASIC - базовый вид аутентификации, используемый, как правило, по умолчанию. Имя пользователя и пароль передаются открытым текстом.
CURLAUTH_DIGEST - является более безопасной версией предидущей.
CURLAUTH_GSSNEGOTIATE - метод аутентификации Microsoft, используемый на серверах этой компании. Поддерживает аутнетификацию Kerberos5. Для использования этого вида аутентификации необходима библиотека GSS.
CURLAUTH_NTLM - метод, так же разработанный и используемый Microsoft, для защиты использует хеширование. Требует наличия OpenSSL.
CURLAUTH_ANY - этот параметр заставляет libcurl выбрать все типы аутентификации, срабатывает метод наиболее подходящий к данному случаю.
CURLAUTH_ANYSAFE - то же самое, только не выбирается CURLAUTH_BASIC аутентификация.

Последний раз редактировалось oleg kutkov; 15.08.2009 в 23:01.
oleg kutkov вне форума Ответить с цитированием
Старый 15.08.2009, 22:35   #3
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Я показал лишь наиболее общие опции, их список, на самом деле, очень велик, подробнее с ними можно ознакомится в HTML документации к библиотеке.
Перед рассмотрением нашего первого примера стоит упомянуть еще две библиотечные функции, а так же функции обратного вызова, о которых я говорил выше.
void curl_easy_reset(CURL *handle) - выполняет повторную инициализацию библиотеки с установкой всеъ опций в значения по умолчанию.
void curl_easy_cleanup(CURL * handle) - Это функция должна вызываться самой последней и вызываться должна обязательно. Она выполняет завершение текущей сессии.
size_t function( void *ptr, size_t size, size_t nmemb, void *stream) - объявление функции, параметра опции CURLOPT_WRITEFUNCTION. Её аргументы:
ptr - указатель на принимаемые данные.
size - размер принимамого блока данных
nmemb - общее количество блоков данных, объем принимаемой информации определяется как size * nmemb
stream - это параметр опции CURLOPT_WRITEDATA, в который производится запись.
Возвращать функция должна общий размер принятой информации.
size_t function( void *ptr, size_t size, size_t nmemb, void *stream) - объявление функции, параметра опции CURLOPT_READFUNCTION. Назначение всех аргументов аналогичное, только здесь выполняется чтение данных из исходного stream и передача libcurl через ptr.
Возвращать функция должна общий размер переданной информации.

Теперь рассмотрим небольшой пример, показывающий инициализацию библиотеки, задание некоторых опций, а так же, знакомящий нас с еще одной важной функцией.

Код:
//подключение необходимых заголовочных файлов
#include <stdio.h>
#include <curl/curl.h>
//главная функция
int main(void)
{
  //уже знакомый объект CURL
  CURL *curl;
  //объект - результат вызова функции curl_easy_perform
  CURLcode res;
  //выполняем инициализацю
  curl = curl_easy_init();
  if(curl) { //проверяем
  //задаем опцию - получить страницу по адресу http://google.com
    curl_easy_setopt(curl, CURLOPT_URL, "google.com");
    //указываем прокси сервер
    curl_easy_setopt(curl, CURLOPT_PROXY, "proxy:8080");
    //задаем опцию отображение заголовка страницы
    curl_easy_setopt(curl, CURLOPT_HEADER, 1);
    //вызываем функцию, выполняющюю все операции, заданные в опциях (получение страницы, передача данных и т.д.), результат - объект типа CURLcode
    res = curl_easy_perform(curl);
    //выполняем обязательное завершение сессии    
    curl_easy_cleanup(curl);
  }
  return 0;
}
Пример крайне прост и понятен, комментарии излишни. Отмечу, что перед выполнением дальнейших действий с данным - необходимо проверить значение res, если резултат - 0, значит все прошло успешно, иначе - ошибка. Её описание можно получить, задав вышеописанный CURLOPT_ERRORBUFFER.

Последний раз редактировалось oleg kutkov; 15.08.2009 в 22:44.
oleg kutkov вне форума Ответить с цитированием
Старый 15.08.2009, 22:35   #4
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Теперь рассмотрим более серьезный пример, получающий и отображающий на стандартном выводе HTML страницу (разумеется в виде самого исходного языка разметки, без рендеринга). Будем использовать все необходимые проверки и функцию обратного вызова.

Код:
//подключаем необходимые заголовочные файлы
#include <string>
#include <iostream>
#include "curl/curl.h"
//подключаем стандартное пространство имен
using namespace std;
//объявляем буфер, для хранения возможной ошибки, размер определяется в самой библиотеке
static char errorBuffer[CURL_ERROR_SIZE];
//объялвяем буфер принимаемых данных
static string buffer;
//функция обратного вызова
static int writer(char *data, size_t size, size_t nmemb, string *buffer)
{
  //переменная - результат, по умолчанию нулевая
  int result = 0;
  //проверяем буфер
  if (buffer != NULL)
  {
    //добавляем к буферу строки из data, в количестве nmemb
    buffer->append(data, size * nmemb);
    //вычисляем объем принятых данных
    result = size * nmemb;
  }
  //вовзращаем результат
  return result;
}

//главная функция
int main(void)
{
    //необходимые CURL объекты
    CURL *curl;
    CURLcode result;
    //инициализируем curl
    curl = curl_easy_init();
    //проверяем результат инициализации
    if (curl)
    {
      //задаем все необходимые опции
      //определяем, куда выводить ошибки
      curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
      //задаем опцию - получить страницу по адресу http://google.com
      curl_easy_setopt(curl, CURLOPT_URL, "google.com");
      //указываем прокси сервер
      curl_easy_setopt(curl, CURLOPT_PROXY, "proxy:8080");
      //задаем опцию отображение заголовка страницы
      curl_easy_setopt(curl, CURLOPT_HEADER, 1);
      //указываем функцию обратного вызова для записи получаемых данных
      curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
      //указываем куда записывать принимаемые данные
      curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
      //запускаем выполнение задачи
      result = curl_easy_perform(curl);
      //проверяем успешность выполнения операции
      if (result == CURLE_OK)      
      //выводим полученные данные на стандартный вывод (консоль)
        cout << buffer << "\n";              
      else      
        //выводим сообщение об ошибке
        cout << "Ошибка! " << errorBuffer << endl;        
  }
  //завершаем сессию
  curl_easy_cleanup(curl);
  return 0;
}
Добавлю к коду небольшие пояснения. Рассмотрим writer - функцию обратного вызова. Ее объявление нам уже знакомо. Функция должна возвращать общее количество принятых данных, иначе ошибка. Наша функция, в случае невыполнения действия записи в буфер будет возвращать значение result по умолчанию - 0. Собственно выполнение записи выполняется только в том случае, если буфер не является NULL. Т.к. мы работаем со строковыми данными - запись в буфер осуществляется вызовом метода append, класса string. Возвращаемое значение - произведение аргументов size и nmemb.
Задание опций дополнительных комментариев, думаю, не требует. После вызова curl_easy_perform происходит проверка возвращенного значения, если оно равно CURLE_OK (этот код определен в curl/curl.h) - происходит вывод содержимого буфера на экран (вывод можно организовать так же в файл или же передать другому приложению/участку, например html рендер-движку), иначе - выводится содержимое errorBuffer, содержащего текст ошибки. В самом конце происходит обязательное закрытие сесии. Этот же пример можно использовать для закачки файлов по фтп, заменив http на ftp, указав полный путь к файлу на сервере, а так же написав в функции writer код, пишуший получаемые байты в файл на диске. Разумеется, в таком случае, необходимо будет убрать вывод на экран.

Я постарался донести общие принципы использования этой библиотеки, больше примеров Вы можете найти в вышеописанном архиве, а так же на сайте разработчика: http://curl.haxx.se/libcurl/c/
Там же доступна обширная и полная документация.

Последний раз редактировалось oleg kutkov; 15.08.2009 в 23:02.
oleg kutkov вне форума Ответить с цитированием
Старый 16.08.2009, 01:09   #5
Mainerz
Новичок
Джуниор
 
Регистрация: 15.08.2009
Сообщений: 4
По умолчанию

А как убрать данные о сервере ?

Код:
Content-Type: text/html; charset=UTF-8
Date: Sat, 15 Aug 2009 21:12:48 GMT
Expires: Mon, 14 Sep 2009 21:12:48 GMT
И etc ...

Последний раз редактировалось Mainerz; 16.08.2009 в 01:14.
Mainerz вне форума Ответить с цитированием
Старый 16.08.2009, 01:21   #6
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Для отображения или не отображения таких данных служит опция CURLOPT_HEADER
Вот вывод, когда значение параметра опции - 1, как в примере ( curl_easy_setopt(curl, CURLOPT_HEADER, 1)):
Код:
HTTP/1.0 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Sat, 15 Aug 2009 21:19:08 GMT
Expires: Mon, 14 Sep 2009 21:19:08 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-Cache: MISS from oleg-server
X-Cache-Lookup: MISS from oleg-server:3128
Via: 1.0 oleg-server:3128 (squid/2.6.STABLE5)
Proxy-Connection: keep-alive

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

И вот вывод, когда параметр данной опции - нулевой, либо же опция вообще не задана:
Код:
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
oleg kutkov вне форума Ответить с цитированием
Старый 19.08.2009, 02:24   #7
DeadHead
 
Регистрация: 02.08.2009
Сообщений: 5
По умолчанию

Спасибо, хорошая статья.
Только одно не понятно, почему ссылка не на последнию версию ?

http://curl.haxx.se/download/curl-7.19.6.zip
DeadHead вне форума Ответить с цитированием
Старый 19.08.2009, 02:54   #8
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Разумеется можно использовать более новые версии, разницы все равно не будет. А в статье указана более старая, т.к. в момент написания я не занимался поиском новых версий, просто взял, то, что у меня уже было
oleg kutkov вне форума Ответить с цитированием
Старый 10.09.2009, 04:12   #9
Despot
 
Регистрация: 10.09.2009
Сообщений: 7
По умолчанию

2 oleg kutkov
libcurl подключается под Borland C++ Builder?
Надо ли что-то особенное делать, чтобы использовать ее под билдером?
Despot вне форума Ответить с цитированием
Старый 10.09.2009, 10:28   #10
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Приветствую. Не подскажите например такое.
Есть файл FILE *f. И я вот начинаю как по обычной схеме инициализирую ставлю опции указываю WriteDataFunction и т.д. Но дело в том, если файл например открывать как a+b, то как указать Curl что уже какая то часть файла скачана, и ненадо эту часть поновой качать ? Т.е. грубо говоря реализовать resume/pause даже после запуска Curl (программы).
BOBAH13 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Работаем с фильтром... nikolai_P Microsoft Office Excel 7 13.03.2009 14:04
Не работаем надстройка xla в 2007 excel (созданная в 2003-м) gysek Microsoft Office Excel 2 19.11.2008 12:06
Показываем объект и только потом работаем дальше celovec Общие вопросы Delphi 7 25.03.2008 15:28
Работаем с РЕЕСТРОМ Altera Windows 7 12.02.2008 18:53