Введение.
Asio – кроссплатформенная библиотека, предназначенная для сетевого взаимодействия и других видов низкоуровневого ввода-вывода. Включает в себя поддержку сокетов, таймеров, последовательных портов, файлов и ссылки Windows. Библиотека написана Крисом Колхофом.
Как и другие части boost, asio является библиотекой исключительно языка C++. Хотя большую часть boost нет необходимости компилировать отдельно от программы, все — же некоторые элементы требуют отдельной компиляции, asio один из таких компонентов.
Компиляция.
Не буду на ней долго останавливаться. Если вы только что достали boost из архива или раньше у вас не было необходимости в тех частях boost, которые требуют компиляции, то необходимо выполнить следующие шаги под Windows:
1. Запустить на выполнение «bootstrap.bat». Ждать. 2. Запустить «bjam.exe». Пойти почитать книгу, так как собираться буст будет долго. 3. Добавить компилятору пути для поиска библиотек буста, которые будут теперь находиться в папке «stagelib»
Обзор библиотеки Boost
Собственно под дистрибутивами Linux последовательность операций для сборки boost схожа.
Устройство.
Главной частью библиотеки является объект класса boost::asio::io_service. Именно он объединяет программу и средства ввода-вывода предоставляемые конкретной операционной системой и он обязательно должен присутствовать в любой программе использующей asio.
boost::asio::io_service the_io_service;
Есть две схемы работы с asio: синхронный и асинхронный. Отличие состоит в том, что в первом случае, выполнение программы идёт последовательно и если следующая команда требует для своего выполнения опрос какого-то устройства, то выполнение основной программы останавливается, до тех пор, пока это устройство не ответит. При асинхронной схеме работы, опрос и ответ устройства не связаны напрямую. Сразу после того, как отправляется запрос на опрос, выполнение основной программы продолжается, а обработка ответа производится в другом месте программы, в то время, когда этот ответ будет получен.
Сейчас опишу работу по синхронной схеме, а в следующий раз по асинхронной, но хочу заметить, что асинхронную обработку можно реализовать отдельно, без использования встроенных в asio средств, но я думаю, что этот способ немного кривой. Зачем что-то изобретать, если все работает так сказать из коробки?
При этом, обработка ответа должна происходить в функции описанной следующим образом:
void func_name( const boost::system::error_code
Вызов функций с приставкой async_ начинает выполнение действие, но обработка ответа начинается лишь после вызова метода run объекта io_service. Ещё один вызов run приведет к остановке выполнения потока в котором вызван метод, до тех пор, пока не будут обработаны все вызванные до этого асинхронные операции(async_).
Сеть.
В asio используется стандарт «сокетов Беркли». Для общение между процессами, компьютерами и т.д. используются так называемые сокеты. Работа с ними различается в зависимости от используемого протокола передачи данных, в этой статье будет рассмотрено лишь использование протокола TCP/IP, так как он гарантирует получение всех отправленных данных в том порядке, в каком они были доставлены и при этом не намного медленнее протокола UDP.
Зачем отключать TURBO BOOST? | Основные плюсы
Инициализация соединения. (Сервер)
Перед тем, как начать передавать данные между участниками TCP соединения один из них должен начать открыть соединения, а другой должен к нему подключиться. Участник открывающий соединение называется сервером, а подключающийся называется клиентом. Серверные TCP функции в asio выполняет объект класса boost::asio::ip::tcp::acceptor.
Перед тем, как открыть соединение, необходимо настроить, откуда ждать этого соединения. Для этого используется объект класса boost::asio::ip::tcp::endpoint. Если endpoint используется в связке с acceptor, то endpoint хранит адреса и порт откуда ждать соединения. Следующий конструктор создает объект endpoint для tcp подключения с форматом IPv4 принимающим запросы с любого адреса на порт 9999:
tcp::endpoint the_endpoint( tcp::v4( ), 9999);
Для создания acceptor, необходимо вызвать конструктор с объектом класса io_service и объектом класса endpoint в качестве параметров:
tcp::acceptor the_acceptor( the_io_service, the_endpoint);
Затем необходимо создать сам сокет, через который и будет происходить передача на стороне сервера. В качестве параметра необходимо передать объект класса io_service.
tcp::socket the_socket( the_io_service);
Метод accept объекта класса acceptor с объектом класса socket переданным в качестве параметра, начинает ожидание подключения, что при синхронной схеме работы приводит к блокированию потока до тех пор, пока какой-нибудь клиент не осуществит подключения:
the_acceptor.accept( the_socket);
После того, как accept будет выполнен, сервер может обмениваться байтами с клиентом через объект класса socket переданный в качестве параметра.
Инициализация соединения. (Клиент)
Для того, чтобы подключиться к серверу на стороне клиента, сначала необходимо настроить endpoint. В данном примере для простоты примера мы знаем адрес и порт к которому будем подключение. Для настройки мы вызываем методы address и port объекта класса передавая им в качестве параметров адрес и номер порта соответственно.
Адрес записывается при помощи четырех байт, но обычно можно встретить запись в виде строки символов из четырёх групп по три цифры разделённых точками. Пример: «127.000.000.001» — адрес который ссылается на тот же самый компьютер. Обычно часть нулей игнорируется при записи: «127.0.0.1».
Для преобразования такой строки к четырём байтам используется функция ip::address_v4::from_string. Функция возвращает структуру типа address, которую в качестве параметра можно передать методу address класса endpoint:
tcp::endpoint the_client_endpoint; the_client_endpoint.port( 9999); the_client_endpoint.address( ip::address_v4::from_string( “127.0.0.1”));
Для подключения к серверу используется метод connect объекта класса socket. В качестве параметра передается объект класса endpoint, указывающий куда подключаться:
tcp::socket the_client_socket( the_io_service); the_client_socket.connect( the_client_endpoint);
В случае успешного соединения, можно приступать к передаче.
Передача.
Сама передача осуществляется с помощью методов read_some/recive и write_some/send объекта класса socket. Методы recive/send являются более низкоуровневыми, с их помощью можно настроить параметры передачи с помощью флагов. Программа не возвращается из методов read_some/write_some до тех пор, пока не будут отослан/принят весь буфер, а recive/send передает столько, сколько можно передать за раз в данной сети. Я буду использовать пару recive/send так как возможность их зависания по идее более низка и методы являются проекцией функций из сокетов Беркли и они мне больше нравятся.
Собственно каждый из этих методов принимает в качестве параметра структуру типа boost::asio::buffer и возвращает сколько байт было послано/принято. Структура используется для того, чтобы привести различные виды контейнеров к единому интерфейсу с которым работают методы передачи и наверно для введения проверки на переполнение. Конструктор buffer принимает в качестве параметров указатель на начало массива байт и размер этого массива.
char buf[256]; strcpy( buf,”message”); int bytes_send=the_socket.write_some( asio::buffer( buf,256)); char dest_buf[256]; memset( dest_buf,0,256); int bytes_recived=the_client_socket.read_some( asio::buffer( dest_buf,256)); std::coutdest_buf;
Вышеприведенный код скорее всего не перешлет весь буфер и передано будет 1-4 байта в зависимости от используемого соединения, поэтому для передачи всего сообщения необходимо с зациклить передачу передавая на каждом шаге цикла определенное число байт игнорируя те байты, которые уже были посланы. Так как принимающая сторона не знает заранее сколько байт было послано и относится именно к данной передаче, то имеет смысл сначала передавть число байт которые будут посланы/приняты. Что-то вроде:
int client::Send( char buffer[],int size)< //buffer – указатель на начало, size – размер передачи. int part=0,len=0; //part – сколько байт передано за раз, len – сколько всего передано the_socket.send( boost::asio::buffer( // Передаем размер данных.
char* last=buffer+size; //last – байт сразу за последним байтом передачи while( bufferlast)< //Пока указатель на начало меньше указателя на конец part=socket->self->send( boost::asio::buffer( buffer,sizeof( buffer))); // отослать часть buffer+=part; // Сдвинуть начало на то, сколько было послано len+=part; // Добавить к размеру сколько послано. > return len; // Вернуть сколько байт послано.
> // Код для получения практически повторяет код передачи, поэтому не нуждается в комментариях. int client::Recive( char buffer[] )< int len,part=0; the_socket.receive( boost::asio::buffer( char* last=buffer+len; while( bufferlast)< part=socket->self->receive( boost::asio::buffer( buffer,sizeof( buffer))); buffer+=part; > return len; >
После того, как передача закончена, необходимо закрыть соединение. Для этого вызывается метод close объекта класса socket, если необходимо запретить соединяться с сервером новым клиентам, то необходимо также вызвать метод close объекта класса acceptor.
the_socket.close( ); the_acceptor.close( );
Обработка ошибок.
Взаимодействие между компьютерами обычно очень неустойчиво к различным факторам, поэтому обработка ошибок стоит в этом вопросе особенно остро. Практически все функции и методы описанные выше могут не сработать или сработать неправильно, поэтому есть перегруженные версии этих методов, которые принимают как дополнительный параметр структуру типа boost::system::error_code. Лучше всего завернуть все что можно в блоки try<>catch(AIDS)<>. Таким образом в случае отказа на подключение к серверу, если его стек соединений полон, можно попробовать подключиться еще раз позже не останавливая выполнение программы.
В общем, это все, что хотел рассказать в этот раз… в следующий раз будет про асинхронную схему передачи и таймеры.
При подготовке статьи использовалось официальное руководство по boost::asio
3 августа 2009 (Обновление: 7 авг 2009)
Источник: gamedev.ru
Boost
Boost — собрание библиотек классов, использующих функциональность языка C++ и предоставляющих удобный кроссплатформенный высокоуровневый интерфейс для лаконичного кодирования различных повседневных подзадач программирования (работа с данными, алгоритмами, файлами, потоками, регулярными выражениями, линейная алгебра, генерация псевдослучайных чисел, обработка изображений, модульное тестирование и т. п.). Версия 1.76 содержит 164 отдельные библиотеки. [2]
Свободно распространяются по лицензии Boost Software License, разработанной для того, чтобы Boost можно было использовать как со свободным, так и с проприетарными программными проектами, вместе с исходным кодом. [3] Проект был создан после принятия стандарта C++, когда многие были недовольны отсутствием некоторых библиотек в STL. Проект является своего рода «испытательным полигоном» для различных расширений языка и части библиотек [4] , которые являются кандидатами на включение в следующий стандарт C++. Многие из основателей Boost входят в комитет по стандартизации C++, и несколько библиотек Boost были приняты для включения в C++ Technical Report 1, стандарт C++11 (например, интеллектуальные указатели, потоки, регулярные выражения, random, ratio, tuple) и стандарт C++17 (например, filesystem, any, optional, variant, string_view). Boost имеет заметную направленность на исследования и расширяемость (метапрограммирование и обобщённое программирование с активным использованием шаблонов).
Сообщество Boost появилось примерно в 1998 году, когда была выпущена первая версия стандарта. С тех пор оно постоянно росло и теперь играет важную роль в стандартизации C++. Несмотря на то что между сообществом Boost и комитетом по стандартизации нет официальных отношений, некоторые разработчики активно участвуют в обеих группах.
Источник: wiki2.org
Русские Блоги
Boost — это библиотека с открытым исходным кодом, поскольку библиотеки с открытым исходным кодом могут быть кроссплатформенными и могут передаваться на разных «аппаратных» платформах. Так что вам нужно установить его.
Установите, затем скомпилируйте и сгенерируйте «библиотеку статических ссылок» или «библиотеки динамических ссылок dll» и так далее.
2. Загрузите пакет установки Boost, который теперь достиг версии 1.60, поэтому для стабильности используйте версию 1.59
После распаковки следующий каталог выглядит следующим образом:


3 скомпилировать форсированные исходные файлы
3.1 После распаковки вы можете щелкнуть файл index.html и установить его через файл инструкций.
(1) Дважды щелкните файл boostrap.bat и запустите bootstrap.bat.
Он сгенерирует четыре файла b2.exe, bjam.exe, project-config.jam и bootstrap.log в корневом каталоге boost.
Среди них b2.exe, bjam.exe, эти два exe одинаковы, bjam.exe — старая версия, b2 — обновленная версия bjam.
3.2 компиляция надстройки с использованием bjam (или b2)
Анализ параметров команды bjam
b2 stage —toolset=msvc-12.0 —with-date_time —stagedir=»D:boost_1_56_0″ link=static runtime-link=static threading=multi debug release
stage указывает, что генерируются только библиотеки (dll и lib), а install также генерирует каталоги include, содержащие заголовочные файлы. Я рекомендую использовать stage, поскольку каталог include, созданный при установке, фактически является каталогом boost после распаковки пакета установки boost (есть только несколько файлов, отличных от hpp, чем каталог include, которые очень малы), так что вы можете использовать его напрямую, а разные IDE имеют Вы можете использовать тот же набор файлов заголовков, который экономит время компиляции и место на жестком диске.
Укажите компилятор, необязательный, такой как borland, gcc, msvc (VC6), msvc-9.0 (VS2008) и т. Д.
vs2008 : msvc-9.0,vs2010 : msvc-10.0,
Выберите, какие библиотеки не компилировать / компилировать. Поскольку мне не нужны python, mpi и другие библиотеки, я исключаю их. Существуют также статические библиотеки, скомпилированные несколькими библиотеками, такими как wave, graph, math, regex, test, program_options, сериализация и сигналы, поэтому без них можно использовать те, которые не нужны. Это может быть выбрано в соответствии с потребностями каждого, и по умолчанию все компилируется. Тем не менее, обратите внимание, что если вы решили скомпилировать python, вам нужна поддержка языка python, вы должны перейти на официальную домашнюю страницу python http://www.python.org/ для загрузки и установки.
Команда для просмотра библиотеки включает в себяbjam —show-libraries。
Используйте stagedir для этапа и префикс для установкиУказывает путь к скомпилированному файлу. Рекомендуется указывать разные каталоги для разных IDE, например, VS2008 соответствует E: SDK boost bin vc9, а VC6 соответствует E: SDK boost bin vc6, в противном случае он будет создан в каталоге, что сложно. управление. Если используется параметр установки, будет также сгенерирован каталог заголовочного файла. Vc9 соответствует E: SDK boost bin vc9 include boost-1_46 boost. Vc6 похож (путь такой громоздкий, поэтому используйте этап хорошо).
Рекомендуемый формат конфигурации: (во избежание загрязнения исходного кода поместите его в ту же структуру каталогов, что и boost)
*** boost ** 159 (исходный файл)
***boost**159_bin_SDKmsvc12_release
***boost**159_bin_SDKmsvc12_debug
***boost**159_bin_SDKgcc11_release
***boost**159_bin_SDKgcc11_debug
Путь к промежуточному файлу, сгенерированному компиляцией. Я не использую его здесь, по умолчанию он находится в корневом каталоге (E: SDK boost), имя каталога bin.v2, после завершения компиляции вы можете удалить весь этот каталог (бесполезно), поэтому нет необходимости устанавливать ,
Создать динамическую библиотеку ссылок / статическую библиотеку ссылок. Чтобы сгенерировать библиотеку динамических ссылок, используйте метод shared, а для создания библиотеки статических ссылок используйте метод static. Как правило, библиотеки Boost могут быть скомпилированы статически, потому что в финальном выпуске программа будет чувствовать себя более громоздкой с Boost DLL.
Динамический / статическийСвязывание библиотек времени выполнения C / C ++, Есть также два метода: общий и статический. Таким образом, ссылка-время выполнения и ссылка могут генерировать всего 4 комбинации, и каждый может выбрать компиляцию в соответствии со своими потребностями.
Однопоточная / многопоточная компиляция. Обычно при написании многопоточных программ вы должны указать многорежимный режим: если вам нужно написать однопотоковую программу, вам также необходимо скомпилировать однопотоковую библиотеку, вы можете использовать однопотоковый режим.
Постройте версию отладки / выпуска. Обычно отладочная версия программы соответствует отладочной версии библиотеки, поэтому обе они компилируются.
Компиляция
Команда для компиляции boost более сложна, особенно не ясны функции link и runtime-link, они имеют 4 типа комбинаций. Что означают эти комбинации?
Поэтому сначала проведите эксперимент, скомпилируйте только библиотеку date_time и наблюдайте за эффектом этих двух параметров.
В первую очередь; b2 stage —toolset=msvc-12.0 —with-date_time —stagedir=»E:eCodeboost_1_56_0binvc12″ link=static runtime-link=static threading=multi debug release Второй; b2 stage —toolset=msvc-12.0 —with-date_time —stagedir=»E:eCodeboost_1_56_0binvc12″ link=static runtime-link=shared threading=multi debug release В-третьих; b2 stage —toolset=msvc-12.0 —with-date_time —stagedir=»E:eCodeboost_1_56_0binvc12″ link=shared runtime-link=shared threading=multi debug release В-четвертых: b2 stage —toolset=msvc-12.0 —with-date_time —stagedir=»E:eCodeboost_1_56_0binvc12″ link=shared runtime-link=static threading=multi debug release В-пятых: b2 stage —toolset=msvc-12.0 —with-date_time —stagedir=»E:eCodeboost_1_56_0binvc12_2″ (дефолтЧтобы избежать перезаписи предыдущих результатов, настройте другой каталог vc12_2 для хранения) В-пятых: b2 stage —toolset=msvc-12.0 —with-date_time —stagedir=»E:eCodeboost_1_56_0binvc12_2″ —build-type=complete(Чтобы избежать перезаписи предыдущих результатов, настройте другой каталог vc12_3 для хранения)
Полученные результаты библиотеки Boost показаны в следующей таблице:
Источник: russianblogs.com