Print This Post Классы для работы с HTTP(S) на C++

Пятница, 6. Январь 2012
Раздел: C/C++, Софт, автор:

Написал кроссплатформенную библиотеку (набор классов) для работы с HTTP(S) на C++, используя последние концепции программирования. Пока что это, пожалуй, beta, так как тестировал я ее совсем мало.

Для сборки библиотеки потребуется собранный Boost (желательно версии 1.48 или выше). Если планируется включение функционала для работы с SSL (HTTPS), то потребуется еще собранная библиотека OpenSSL. Также в обязательном порядке требуется поддержка компилятором C++11. Сами заголовочные файлы библиотеки не включают ни заголовочные файлы boost, ни OpenSSL.

Для тех, кто захочет использовать библиотеку для написания чего-то жестоко многопоточного (конечно, спамеров, а что же еще подобное пишут с дохера потоками), учтите, что каждый запрос создает 1 дополнительный фоновый поток, т.е. количество потоков, используемых приложением, увеличивается вдвое. Такая особенность работы связана с тем, что в своем ядре библиотека использует boost::asio::io_service для контроля времени выполнения запроса (словом, внутри библиотеки всё происходит асинхронно).

Краткое описание возможностей класса:
[+] GET/POST/прочие запросы с использованием HTTP/1.0
[+] Поддержка HTTPS
[+] Поддержка multipart-POST запросов с возможностью загрузки произвольного количества файлов любого размера
[+] Автоматический менеджмент Cookies
[+] Автоматические переходы по Location-редиректам
[+] Поддержка скачивания больших файлов
[+] Поддержка HTTP/HTTPS/SOCKS5-прокси с авторизацией и без
[+] Возможность добавлять собственные HTTP-заголовки в запрос
[+] Поддержка автоматической обработки параметров (urlencode)
[+] Возможность задать таймаут на любой запрос
[+] Множество вспомогательных функций (urlencode, base64 и т.п.)

Классы потоконебезопасны, организация синхронизации должна производиться на вашей стороне в случае использования одного и того же экземпляра какого-либо класса в нескольких потоках сразу.

Далее я по пунктам приведу краткое описание возможностей библиотеки с примерами.

1. Простой пример HTTP GET-запроса.

#include <iostream>
#include <string>
#include <simple_http/simple_http.h>
#include <simple_http/http_endpoint.h>
#include <simple_http/functions.h>
 
int main()
{
	//Создали объект http_sync_connection
	simple_http::http_sync_connection conn;
 
	/* Отправили GET-запрос серверу и получили ответ
	Поддерживаемые адреса в функции from_string() имеют вид
	http://kaimi.ru
	http://kaimi.ru/test/
	https://www.google.com/ -> если библиотека собрана с поддержкой SSL
	http://mail.ru:80/?xxx=123
	http://test.ru/qwerty/xxx.php?a=1&b=2&c=3
	*/
	std::string ret = conn.get(simple_http::http_endpoint::from_string("http://localhost/uploader/test.php?xxx=123&zzz=123"));
 
	//Получили тело ответа и вывели его в консоль
	std::cout << simple_http::get_body(ret) << std::endl;
 
	return 0;
}

Пара строк кода, чтобы совершить GET-запрос. Что может быть проще? Дальнейшие примеры не будут уступать этому по простоте.

На заметку. Метод simple_http::http_endpoint::from_string создает экземпляр класса http_endpoint, который разделяет переданную ему строку URL на следующие независимые элементы:
- HTTP/HTTPS
- HOST/IP address
- порт (если есть)
- URI (если есть)
- параметры запроса (если есть)

Если передать объект класса http_endpoint в метод get, то параметры будут переданы методом GET, а если в post, то, соответственно, методом POST.

2. Запросы с автоматическим менеджментом Cookies.
Для автоматического менеджмента Cookies существует класс cookie_manager.

	simple_http::http_sync_connection conn;
	simple_http::cookie_manager manager; //создали менеджер
	conn.set_auto_cookie_manager(manager); //прикрепили его к HTTP-классу

Далее могут следовать любые HTTP(S)-запросы, кукисы для них будут автоматически сохраняться менеджером и подставляться, когда это необходимо. Класс менеджера Cookies позволяет получить действительные Cookies для заданного домена, пути и т.д. Также можно добавлять собственные Cookies, они будут использоваться при HTTP(S)-запросах.

Для отключения автоматического менеджмента Cookies используется функция remove_auto_cookie_manager.

Класс cookie_manager имеет множество методов, позволяющих получить определенные Cookies, добавить новые, удалить какие-то определенные или все сразу и т.д. Описание я приводить не буду, так как они имеют достаточно очевидные названия и прототипы.

3. Установка таймаута на запрос.
Для того, чтобы установить максимальное время, которое может выполняться запрос, используется функция set_query_timeout, которая принимает как аргумент максимальное значение времени в секундах. По умолчанию на каждый запрос отводится 60 секунд. Если при запросе используются прокси, то время их отклика включается в этот таймаут.

4. Использование http proxy/socks5 с авторизацией или без для запросов.
Для установки proxy для запросов используются следующие методы класса http_sync_connection:

	void set_proxy(const std::string& address, unsigned short port, proxy_type ptype);
	void set_proxy(const std::string& address, unsigned short port, proxy_type ptype, const std::string& login, const std::string& password);

address - строка адреса прокси (IP-адрес или имя хоста).
port - порт прокси
ptype - тип прокси: proxy_none - убрать прокси, proxy_http - HTTP-прокси, proxy_socks5 - SOCKS5-прокси.
login, password - логин и пароль прокси-сервера.

	void clear_proxy();

Позволяет очистить текущий прокси-сервер.

5. Использование автоматических переходов по редиректам.

	void enable_auto_redirect_follow(bool follow = true);

Включает/отключает автоматические переходы по редиректам (Location). По умолчанию выключено.

	void enable_cross_domain_redirects(bool allow = true);

Включает/отключает переходы по Location на другие домены (например, если встретится редирект с mail.ru на yandex.ru, то при выключенной опции он не будет произведен автоматически). По умолчанию включено.

	void set_max_redirect_count(unsigned long count = 10);

Устанавливает максимальное количество автоматических переходов по редиректам. По умолчанию 10.

	std::string get_last_redirect_domain() const;
	std::string get_last_redirect_uri() const;
	std::string get_last_redirect_line() const;
	unsigned short get_last_redirect_port() const;

Данные функции позволяют получить информацию о последнем произведенном редиректе: домен, URI, строку адреса редиректа и порт соответственно.

	unsigned long get_recent_redirect_count() const;

Позволяет получить количество сделанных авторедиректов во время последнего HTTP(S)-запроса.

Если библиотека собрана без поддержки SSL, и в каком-либо ответе от сервера встречается редирект с HTTP на HTTPS, он произведен не будет, даже если включена опция автоматического перехода по редиректам.

6. Дополнительные заголовки запроса.
Для добавления/удаления дополнительных заголовков в запрос используются следующие функции:

	void add_query_header(const std::string& name, const std::string& value);
	bool remove_query_header(const std::string& name);
	void clear_query_headers();

Первая добавляет дополнительный заголовок с именем name и значением value.
Вторая удаляет дополнительный заголовок с именем name.
Третья удаляет все дополнительные заголовки.

7. User-agent.
Для установки заголовка User-agent есть удобная функция

	void set_user_agent(const std::string& user_agent = "");

Если ей передана пустая строка, заголовок User-agent отсылаться не будет.

8. Отправка запросов без использования http_endpoint.
Иногда может потребоваться отправка запросов без использования данного упрощающего класса (например, если требуется передать HTTP Referer или часть параметров методом GET, а другую часть - методом POST).

Класс http_sync_connection имеет следующие функции:

	std::string get(const std::string& uri, const std::string& parameters = "", const std::string& cookies = "", const std::string& referer = "");
	std::string post(const std::string& uri, const std::string& parameters = "", const std::string& cookies = "", const std::string& referer = "");
	std::string query(const std::string& method, const std::string& uri, const std::string& parameters = "", const std::string& cookies = "", const std::string& referer = "");
 
	std::string get(const http_endpoint& ep, const std::string& cookies = "", const std::string& referer = "");
	std::string post(const http_endpoint& ep, const std::string& cookies = "", const std::string& referer = "");
	std::string query(const std::string& method, const http_endpoint& ep, const std::string& cookies = "", const std::string& referer = "");

Первые две отправляют на сервер, соответственно, GET и POST запрос. Третья позволяет явно задать тип запроса (например, "GET", "POST", "HEAD").
uri - Service-URI
parameters - параметры, которые необходимо передать на сервер. Функция get передаст их методом GET, а post - методом POST.
cookies - cookie, которые необходимо добавить в запрос. Если включен автоматический менеджмент Cookies, эти кукисы будут добавлены к тем, которые отсылаются менеджером cookies.
referer - HTTP-Referer.

Три последние функции отличаются от первых трех только тем, что позволяют задать домен, порт, URI и параметры запроса с помощью класса http_endpoint.

9. Отправка файлов на сервер (Multipart POST-запросы).
Класс http_sync_connection поддерживает загрузку файлов на сервер с помощью multipart-запросов. Имеется три функции:

	std::string multipart_post(const std::string& uri, const std::string& parameters = "", const std::string& cookies = "", const std::string& referer = "");
	std::string multipart_post(const std::string& uri, const std::string& multipart_file_parameter_name, multipart_file& file, const std::string& parameters = "", const std::string& cookies = "", const std::string& referer = "");
	std::string multipart_post(const std::string& uri, std::map<std::string, multipart_file*>& files, const std::string& parameters = "", const std::string& cookies = "", const std::string& referer = "");
 
	std::string multipart_post(const http_endpoint& ep, const std::string& multipart_file_parameter_name, multipart_file& file, const std::string& cookies = "", const std::string& referer = "");
	std::string multipart_post(const http_endpoint& ep, std::map<std::string, multipart_file*>& files, const std::string& cookies = "", const std::string& referer = "");
	std::string multipart_post(const http_endpoint& ep, const std::string& cookies = "", const std::string& referer = "");

Их параметры аналогичны вышеописанным get, post, query. Первый вариант функции ничем не отличается от функции post за исключением того, что данные будут отсылаться multipart-запросом.

Второй вариант имеет дополнительные параметры:
multipart_file_parameter_name - имя прикрепляемого к запросу файла
file - сам файл (объект класса multipart_file).

Третий вариант позволяет прикрепить сразу несколько файлов к запросу. Для этого используется параметр files - список файлов с именами.

Три последние функции отличаются от первых трех только тем, что позволяют задать домен, порт, URI и параметры запроса с помощью класса http_endpoint.

Класс multipart_file объявлен в заголовочном файле multipart_file.h и позволяет задать файл либо по его пути (физический файл операционной системы), либо как буфер данных.

Пример загрузки файла на сервер:

int main()
{
	simple_http::http_sync_connection conn;
 
	//Создали объект класса multipart_file
	simple_http::multipart_file file("file.bmp", "C:\\image.bmp");
 
	//Загрузили этот файл на сервер и считали ответ
	std::cout << conn.multipart_post(simple_http::http_endpoint::from_string("http://localhost/uploader/5.php"), "uploaded_file", file)
		<< std::endl;
 
	return 0;
}

10. Кеширование DNS-запросов.

	void set_connenction_cache(bool enabled = true);

Эта функция позволяет включить или отключить кеширование DNS-запросов. По умолчанию кеширование включено. Если вы делаете много запросов подряд на один и тот же сервер, и данная функция включена, определение IP-адреса хоста будет производиться только один раз при первом запросе.

11. Автоматическая обработка параметров запроса (urlencode).
По умолчанию данная возможность выключена. Для ее включения/отключения используется функция

	void enable_auto_urlencode(bool enable = true);

Если данная функция включена, будет производиться автоматическая обработка (urlencode) параметров запросов HTTP(S).

12. Callback при загрузке контента.
Если вы скачиваете большой файл или общаетесь с очень медленным сервером, возможно, есть смысл настроить callback, который будет вызываться при загрузке содержимого страницы.

	template<typename Handler>
	void set_http_load_callback(Handler handler)

Данная функция позволяет установить коллбек, который будет вызываться в процессе загрузки контента с сервера.

	void clear_http_load_callback();

Данная функция отключает callback на чтение данных.

	void clear_input_after_callback(bool clear = true);

Данная функция устанавливает, должно ли очищаться возвращаемое значение функций get, post, query, multipart_post при использовании коллбека. По умолчанию включено.

	void set_callback_min_transfer_amount(unsigned long bytes);

Данная функция позволяет установить минимальное количество байтов, которое должно быть принято с сервера до вызова коллбека. По умолчанию 1.

	void set_callback_option(http_callback_option option = get_everything);

Данная функция позволяет настроить поведение коллбека. По умолчанию это get_everything, т.е. из сокета читается весь контент. Доступны также значения get_headers_only (будут считаны только заголовки) и get_body_only (будет считано только тело).

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

Пример использования коллбека для скачивания большого файла (при этом оперативной памяти будет расходоваться совсем немного):

#include <iostream>
#include <string>
#include <fstream>
#include <boost/bind.hpp>
#include <simple_http/simple_http.h>
#include <simple_http/http_endpoint.h>
#include <simple_http/functions.h>
 
//Функция сохранения скачанной части данных в файл
bool filereader(const std::string& s, std::ofstream& file, unsigned long& downloaded)
{
	downloaded += s.length();
	//Сохраняем кусок скачанного файла
	file.write(s.data(), s.length());
	//Выводим количество скачанных байтов данных
	std::cout << "\rDownloaded: " << downloaded;
	return true; //Возвращаем true - продолжаем чтение
}
 
int main()
{
	simple_http::http_sync_connection conn;
 
	//Открываем файл на запись
	std::ofstream file("downloaded_boost.7z", std::ios::out | std::ios::binary | std::ios::trunc);
	unsigned long downloaded = 0;
 
	//Устанавливаем коллбек
	conn.set_http_load_callback(boost::bind(filereader, _1, boost::ref(file), boost::ref(downloaded)));
 
	//Получаем только тело ответа (сам файл, заголовки нам не нужны сейчас)
	conn.set_callback_option(simple_http::get_body_only);
 
	//Читаем пачками минимум по 50 кб, чтобы было быстрее и коллбек реже вызывался
	conn.set_callback_min_transfer_amount(50000);
 
	//Запускаем чтение
	conn.get(simple_http::http_endpoint::from_string("http://localhost/boost.7z"));
 
	//Готово, файл скачался. Функция get в этом случае вернет пустую строку, так как  это опция по умолчанию
	//Это необходимо для экономии оперативной памяти при скачивании больших файлов, да и результат мы уже получили
	//и сохранили, так что дополнительно получать контент нет смысла.
	std::cout << std::endl << "Finished!" << std::endl;
 
	return 0;
}

13. Вспомогательные функции.
Файл utils.h содержит объявления различных вспомогательных функций для перекодирования base64, urlencode и т.д.
Файл functions.h содержит объявления вспомогательных функций для работы с ответами HTTP.

14. Исключения
Файл http_error.h содержит объявление класса, используемого для возбуждения исключений, возникающих при работе классов simple_http. Все примеры приведены без обработки исключений, чтобы сосредоточиться на их сути. Вообще, все вызовы функций и методов классов неймспейса simple_http должны оборачиваться в обработчик исключений. Класс http_error позволяет получить как текст сообщения об ошибке, так и его код (они перечислены внутри класса).

15. Сборка с поддержкой SSL.
Для того, чтобы собрать библиотеку с поддержкой SSL (чтобы работали HTTPS-запросы), необходимо задать директиву препроцессора SSL_SUPPORT. Если поддержка SSL отключена, класс http_sync_connection будет бросать исключение при попытке произвести HTTPS-запрос.

Наконец, последний пример - авторизуемся на Форуме АНТИЧАТ и получаем количество новых приватных сообщений и общее их количество.

#include <iostream>
#include <string>
#include <boost/regex.hpp>
#include <simple_http/simple_http.h>
#include <simple_http/http_endpoint.h>
#include <simple_http/cookie_manager.h>
#include <simple_http/http_error.h>
 
#pragma comment(lib, "simple_http.lib")
#pragma comment(lib, "libeay32.lib")
#pragma comment(lib, "ssleay32.lib")
 
int main()
{
	std::string login = "ВАШ ЛОГИН";
	std::string password = "ВАШ ПАРОЛЬ";
 
	try
	{
		simple_http::http_sync_connection conn; //создали экземпляр класса http_sync_connection
		simple_http::cookie_manager manager; //создали менеджер cookies
		conn.set_auto_cookie_manager(manager); //прикрепили его к HTTP-классу
 
		//Делаем GET-запрос на главную страницу, чтобы получить начальные Cookies
		conn.get(simple_http::http_endpoint::from_string("https://forum.antichat.ru/index.php"));
 
		//Добавляем HTTP-Referer'а
		conn.add_query_header("Referer", "https://forum.antichat.ru/index.php?");
		//Включаем автоматическую обработку параметров (urlencode)
		conn.enable_auto_urlencode();
 
		//Делаем POST-запрос, чтобы авторизоваться
		std::string login_page = conn.post(
			simple_http::http_endpoint::from_string("https://forum.antichat.ru/login.php?do=login&cookieuser=1&forceredirect=1&s=&vb_login_username=" + login + "&vb_login_password=" + password));
 
		//Если авторизация успешна
		if(login_page.find("Спасибо, что зашли, ") != std::string::npos)
		{
			std::cout << "Correct login and password" << std::endl;
 
			//Снова получаем главную страницу, будучи авторизованными
			std::string index_page = conn.get(simple_http::http_endpoint::from_string("https://forum.antichat.ru/index.php"));
 
			//Получаем количество ПМов
			static boost::regex pm_match("ЛИЧНАЯ ПОЧТА</a> \\(<b>(\\d+)</b>/(\\d+)\\)");
			boost::smatch what;
			//И выводим, сколько у нас новых ПМов, и сколько их всего
			if(boost::regex_search(index_page, what, pm_match))
				std::cout << "New PMs: " << what[1].str() << ", total PMs: " << what[2].str() << std::endl;
		}
		else
		{
			//Иначе говорим, что введен неправильный логин или пароль
			std::cout << "Incorrect login or password" << std::endl;
		}
	}
	catch(const simple_http::http_error& e)
	{
		//Если произошла какая-то ошибка, выведем ее и завершим работу
		std::cout << "Error: " << e.what() << std::endl;
	}
 
	return 0;
}

Вот и всё! Приведенной информации вполне достаточно, чтобы полноценно работать с библиотекой.

Выкладываю исходники библиотеки и последнего примера: simple_http.zip. В комплекте - файл солюшена и проектов Visual Studio 2010. Не забудьте прописать свои пути к boost'у и OpenSSL (если вам потребуется поддержка HTTPS).

Также рекомендую почитать

 Обсудить на форуме


Получать обновления на почту:     

Метки: , , , , , , , , , , .

Комментариев: 55 к “Классы для работы с HTTP(S) на C++”


  1. имя :

    Мне кажется, или получить заголовки ответа с помощью данной библиотеки не получится?

    [Ответить]

    dx:

    Получится:

    #include simple_http/functions.h

    simple_http::get_headers

    даже две перегрузки имеет

    [Ответить]

  2. Потестим, позже отпишусь)

    [Ответить]

  3. Изобрели CurlPP?

    [Ответить]

    dx:

    Типа того, только без Curl, а на boost::asio.

    [Ответить]


  4. max :

    Спасибо за код, выглядит интересно. Но почему большинство функций статические? simple_http::http_endpoint::from_string и тд. И почему в примерах не юзаете неймспейсы? Повторяющегося кода было бы меньше.

    [Ответить]

    dx:

    Статические функции в коде олько те, которые могут работать вне класса. Зачем добавлять функциональность внутрь класса, если она, по сути, не зависимая? Об этом еще Скотт Мейерс писал, кажется, да или посмотри на буст: boost::asio::ip::tcp::endpoint::from_string и подобные вызовы.

    В примерах на 5 строк юзать неймспейсы? Да и что подразумевается под использованием неймспейсов, написать строку "using namespace simple_http"? Я не сторонник разыменовывания всего подряд, тем более, что это может породить конфликты имен. Если много писать, лучше сделать укороченный алиас неймспейсу.

    [Ответить]

  5. В общем попробовал я брут написать, вроде работает)

    [Ответить]


  6. Гость :

    А никто не может рассказать как включать его в свои проекты? Положил в include в VS, при компиляции выдает "error LNK2028: ссылка на неразрешенную лексему (0A000089) "public: class std::basic_string<char,struct std::char_traits..."

    [Ответить]

    dx:

    Я же писал, что либа требует boost собранного, и сама тоже требует сборки.
    Если требуется поддержка ssl, то необходима еще и OpenSSL собранная.
    Пример включения в проект лежит в архиве.

    [Ответить]


  7. Chrome~ :

    [+] Поддержка multipart-POST запросов с возможностью загрузки произвольного количества файлов любого размера

    Он вроде как загружает файлы в ОП перед отправкой, поэтому зависит от количества свободной ОП.

    Трудно читать код на C++ после Delphi, очень непривычно, что можете посоветовать?

    [Ответить]


  8. Chrome~ :

    Где можно прочитать про стандарты C/C++, желательно на русском и какую IDE можете посоветовать кроме MS Visual Studio.

    [Ответить]

    dx:

    Стандарт C++ - это обычный документ, который можно брать и читать. IDE - смотря под какую ОС. Visual Studio последних версий, имхо, одна из самых удобных.

    [Ответить]


  9. Гость :

    При попытки компиляции примера:

    error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall simple_http::http_sync_connection::http_sync_connection(void)" (??0http_sync_connection@simple_http@@QAE@XZ) в функции _main C:\Users\Denis\Downloads\Архивы\simple_http\examples\main.obj examples

    Пути к бусту указаны

    [Ответить]

    Kaimi:

    Путь к lib-файлу либы то тоже надо указать

    [Ответить]


  10. z1p0 :

    странно , буст скомпилил и собрал , да и примеры бустовые идут на ура , вот только почемуто при компиле отправки потс запроса (1 ый ваш пример) , выдаёт типа от что :
    1>c:\program files\microsoft visual studio 9.0\vc\include\simple_http\simple_http.h(110) : error C2039: function: не является членом "std"
    1>c:\program files\microsoft visual studio 9.0\vc\include\simple_http\simple_http.h(110) : error C2143: синтаксическая ошибка: отсутствие ";" перед "c:\program files\microsoft visual studio 9.0\vc\include\simple_http\simple_http.h(110) : error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
    1>c:\program files\microsoft visual studio 9.0\vc\include\simple_http\simple_http.h(110) : error C2238: непредвиденные лексемы перед ";"
    В сём мб трабла ? Буст собран , SSL не нужен :)

    [Ответить]

    dx:

    Можно закомментировать этот момент (если коллбеки не нужны), он компилируется только в студии 2010 и выше и в последних gcc. Это C++11.
    Ну или поставить новую студию)

    [Ответить]


  11. and1 :

    simple_http::http_sync_connection conn -На это он выдает:

    msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: __thiscall std::_Lockit::~_Lockit(void)" (??1_Lockit@std@@QAE@XZ) already defined in libcpmtd.lib(xlock.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: __thiscall std::_Lockit::_Lockit(int)" (??0_Lockit@std@@QAE@H@Z) already defined in libcpmtd.lib(xlock.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)" (?_Debug_message@std@@YAXPB_W0I@Z) already defined in libcpmtd.lib(stdthrow.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "void __cdecl std::_Xout_of_range(char const *)" (?_Xout_of_range@std@@YAXPBD@Z) already defined in libcpmtd.lib(xthrow.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: __thiscall std::_Container_base12::~_Container_base12(void)" (??1_Container_base12@std@@QAE@XZ) already defined in main.obj
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: __thiscall std::_Container_base12::_Container_base12(void)" (??0_Container_base12@std@@QAE@XZ) already defined in main.obj
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: void __thiscall std::_Container_base12::_Orphan_all(void)" (?_Orphan_all@_Container_base12@std@@QAEXXZ) already defined in main.obj
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "void __cdecl std::_Xlength_error(char const *)" (?_Xlength_error@std@@YAXPBD@Z) already defined in libcpmtd.lib(xthrow.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: struct std::_Iterator_base12 * * __thiscall std::_Container_base12::_Getpfirst(void)const " (?_Getpfirst@_Container_base12@std@@QBEPAPAU_Iterator_base12@2@XZ) already defined in simple_http.lib(simple_http.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: static int __cdecl std::numeric_limits::max(void)" (?max@?$numeric_limits@H@std@@SAHXZ) already defined in simple_http.lib(simple_http_impl.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: void __thiscall std::_Container_base12::_Swap_all(struct std::_Container_base12 &)" (?_Swap_all@_Container_base12@std@@QAEXAAU12@@Z) already defined in simple_http.lib(utils.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: static unsigned int __cdecl std::numeric_limits::max(void)" (?max@?$numeric_limits@I@std@@SAIXZ) already defined in simple_http.lib(simple_http.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: "public: __thiscall std::exception::exception(char const * const &)" (??0exception@std@@QAE@ABQBD@Z) already defined in LIBCMTD.lib(stdexcpt.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: "public: virtual __thiscall std::exception::~exception(void)" (??1exception@std@@UAE@XZ) already defined in LIBCMTD.lib(stdexcpt.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: "public: __thiscall std::exception::exception(class std::exception const &)" (??0exception@std@@QAE@ABV01@@Z) already defined in LIBCMTD.lib(stdexcpt.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: __wassert already defined in LIBCMTD.lib(wassert.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _memmove already defined in LIBCMTD.lib(memmove.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _wcslen already defined in LIBCMTD.lib(wcslen.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: __invalid_parameter already defined in LIBCMTD.lib(invarg.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: __CrtDbgReportW already defined in LIBCMTD.lib(dbgrptw.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: "public: bool __thiscall type_info::operator==(class type_info const &)const " (??8type_info@@QBE_NABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _tolower already defined in LIBCMTD.lib(tolower.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _towlower already defined in LIBCMTD.lib(towlower.obj)
    1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
    1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _strerror already defined in LIBCMTD.lib(strerror.obj)
    1>LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library
    1>D:\example\simple_http (1)\Debug\examples.exe : fatal error LNK1169: one or more multiply defined symbols found

    [Ответить]


  12. and1 :

    И еще в примерах вызывается либа "libboost_regex-vc100-mt-sgd-1_48.lib" (например), а boost (v.1.48) собрал "libboost_regex-vc100-mt-gd-1_48.lib" может в этом дело?

    [Ответить]


  13. and1 :

    Как правильно подключить все?

    [Ответить]

    dx:

    Собрать всё с одинаковыми рантаймами (например, статические отладочные или статические релизные), и все без проблем слинкуется.
    Примеры вообще никак не собраны и никакие либы там не вызываются. Надо ставить просто везде одинаковый параметр Code Generation в студии и собирать буст с теми же самыми настройками.

    [Ответить]


  14. z1p0 :

    СтраHHо , устаHовил 10 студию , буст поставвил (всe примэры бустовскиe компилятся Hа ура !!), одHако пи выполHeHии вышe описаHHого кода , вылазиeт :
    1>crea.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall simple_http::http_sync_connection::~http_sync_connection(void)" (??1http_sync_connection@simple_http@@QAE@XZ) в функции _main
    1>crea.obj : error LNK2019: ссылка на неразрешенный внешний символ "class std::basic_string<char,struct std::char_traits,class std::allocator > __cdecl simple_http::get_body(class std::basic_string<char,struct std::char_traits,class std::allocator > const &)" (?get_body@simple_http@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABV23@@Z) в функции _main
    1>crea.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: class std::basic_string<char,struct std::char_traits,class std::allocator > __thiscall simple_http::http_sync_connection::get(class simple_http::http_endpoint const &,class std::basic_string<char,struct std::char_traits,class std::allocator > const &,class std::basic_string<char,struct std::char_traits,class std::allocator > const &)" (?get@http_sync_connection@simple_http@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABVhttp_endpoint@2@ABV34@1@Z) в функции _main
    1>crea.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: static class simple_http::http_endpoint __cdecl simple_http::http_endpoint::from_string(class std::basic_string<char,struct std::char_traits,class std::allocator > const &)" (?from_string@http_endpoint@simple_http@@SA?AV12@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) в функции _main
    1>crea.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall simple_http::http_sync_connection::http_sync_connection(void)" (??0http_sync_connection@simple_http@@QAE@XZ) в функции _main
    В чём мб трабла ??

    [Ответить]


  15. z1p0 :

    П.с , КАими писал мол , Путь к lib-файлу либы то тоже надо указать.. Это как , и про какую лтбу ??Файлы из папки SТage буста , я указал ..

    [Ответить]

    dx:

    Если ты собираешь пример работы с либой, то перед этим как бы надо и саму либу собрать, а потом в примере указать путь к ее lib-файлу.

    [Ответить]


  16. and1 :

    В отдельности в проекте работает и boost и openssl, но стоит добавить хотя бы "simple_http::http_sync_connection conn;" линкер выдает две ошибки!

    1>asd.obj : error LNK2019: unresolved external symbol "public: __thiscall simple_http::http_sync_connection::~http_sync_connection(void)" (??1http_sync_connection@simple_http@@QAE@XZ) referenced in function _main
    1>asd.obj : error LNK2019: unresolved external symbol "public: __thiscall simple_http::http_sync_connection::http_sync_connection(void)" (??0http_sync_connection@simple_http@@QAE@XZ) referenced in function _main

    если же пишем #pragma comment (lib, "simple_http.lib") то вообще беда...
    dx, выручайте))

    [Ответить]

    dx:

    Именно #pragma comment (lib, "simple_http.lib") и надо написать, учтя, чтобы буст и либа были собраны с одинаковыми параметрами Code generation (рантаймы студии).

    [Ответить]


  17. z1p0 :

    Дык а как иё собрать ??Я так поHИмаю рeчь идёт о сборкe вашэй либы , а He бустовской ??Бустовая уж собраHа , я каHуч извиHяюсь за тупизHу , просто curl He качаицо ЫЫ

    [Ответить]

    dx:

    Качайте лучше curl

    [Ответить]


  18. and1 :

    А как узнать/ посмотреть с какими рантаймами был создан boost?
    собирал так:
    1.bootstrap.bat
    2.bjam.exe --toolset=msvc-10.0 --build-type=complete
    Его boost из студии надо собрать? или в проекте Вашей библиотеке рантаймы поменять проще будет и пере собрать?

    [Ответить]

    dx:

    Советую собрать буст в двух вариантах:

    bjam variant=debug link=static threading=multi runtime-link=static
    bjam variant=release link=static threading=multi runtime-link=static

    (ну и тулсет указать, если их несколько, да)

    После этого ставить в проектах, в которых буст используется, параметр Code generation = MT для релизных сборок и MTd для отладочных.
    Библиотеку, соответственно, в студии с такими флагами и собирать.

    [Ответить]


  19. and1 :

    Собрал, флаги выставил. Все равно!
    1>asd.obj : error LNK2019: unresolved external symbol "public: __thiscall simple_http::http_sync_connection::~http_sync_connection(void)" (??1http_sync_connection@simple_http@@QAE@XZ) referenced in function _main
    1>asd.obj : error LNK2019: unresolved external symbol "public: __thiscall simple_http::http_sync_connection::http_sync_connection(void)" (??0http_sync_connection@simple_http@@QAE@XZ) referenced in function _main
    1>C:\Users\Администратор\Downloads\simple_http\Debug\asd.exe : fatal error LNK1120: 2 unresolved externals

    [Ответить]

    dx:

    Ну блин, #pragma comment(lib, "simple_http") же, сколько раз писать еще

    [Ответить]


Оставьте ваш комментарий