Для работы с асинхронными сокетами необходимо изучить основы библиотеки Boost::Asio, а именно класс io_service. Данный класс предоставляет базовую функциональность для организации асинхронной работы, поэтому рассмотрим подробнее особенности работы с ним. Диаграмма классов представлена на рисунке1.1
1.4.1.1. Класс io_service
Io_service – класс, предоставляющий базовую функциональность асинхронного ввода/вывода для различных операционных систем. Основная деятельность объекта данного класса заключается в том, чтобы ожидать конца асинхронной операции и вызывать определённый обработчик.
Таблица 1.1
Конструктор |
io_service(); |
После объявления объекта необходимо вызвать метод run(). При этом объект заберёт на себя управление, то есть заблокирует поток. Если в вашем приложении есть графический интерфейс, то необходимо вызывать метод run() в другом потоке.
|
Таблица 1.2 |
|
|
|
|
Функция |
std::size_t run(); |
|
Описание функции |
Забирает управление потоком, начинает ожидать конец |
|
|
асинхронных операций и вызывать их обработчики. Возвращает |
|
|
количество обработчиков, которые должны обрабатываться |
|
|
объектом. |
|
В случае если асинхронных операций нет, вызывается метод stop(), который переводит объект в пассивное состояние и возвращает управление.
|
Таблица 1.3 |
|
|
|
|
Функция |
void stop(); |
|
Описание функции |
Переводит объект в пассивное состояние и возвращает |
|
|
управление. |
|
1.4.1.2. Класс work
Чтобы объект продолжал выполнять обработку асинхронных операций, даже когда отложенных операций нет, необходимо нагрузить его работой, для этого используется класс io_service::work.
|
Таблица 1.4 |
|
|
|
|
Конструктор |
io_service::work( |
|
|
boost::asio::io_service & io_service |
|
|
); |
|
Описание параметров |
io_service – объект, который будет выполнять обработку. |
|
После создания объекта класса Work, объект io_service будет находиться в пассивном режиме. Далее необходимо вызвать метод run() для io_service. В этом случае io_service будет работать пока не будет вызван метод stop() или не уничтожен объект Work.
Все обработчики, которые будут вызваны, выполняется в том же потоке, где вызван метод run();
1.4.1.3. Класс thread
Для организации потоков используется класс boost::thread.
|
Таблица 1.5 |
|
|
|
|
Конструктор перемещения |
thread( |
|
|
thread&& other |
|
|
) noexcept; |
|
Описание параметров |
other –функция, которая будет выполняться в другом |
|
|
потоке. |
|
Рассмотрим пример:
У нас есть объект io_service. Для того, чтобы при запуске метода run() объект не забрал управление, мы хотим перенести запуск этого метода в другой поток.
boost::asio::io_service service ();
Для начала необходимо написать функцию, которая будет исполняться в другом потоке.
void run_io_service()
{
boost::asio::io_service::work work(service); service.run();
}
Теперь необходимо создать поток и перенести исполнение вышеописанной функции в него.
boost::thread thread(run_io_service);
После этого функция run_io_service() начнёт выполняться в другом потоке.
1.4.1.4. Функция bind
Если необходимо использовать функцию с параметрами или функцию пользовательского класса, то воспользуемся boost::bind(), которая свяжет саму функцию и её параметры.
Пример:
1) Связка с параметрами
int number;
void run_io_service(int number);
boost::thread thread(boost::bind(run_io_service,number));
2) Связка с функцией объекта
int number; MyСlass * this;
void MyClass::run_io_service(int number);
boost::thread thread(boost::bind(MyClass::run_io_service,this,number));
1.4.1.5. Классы для непосредственной работы с сокетами
Ip::tcp::socket - класс для организации потокового сокета. Предоставляет унифицированный интерфейс для работы с потоковыми сокетами. В отличие от Socket API, Ip::tcp::socket не может прослушивать порт, для этого существует специализированный класс ip::tcp::acceptor.
Ip::tcp::acceptor – класс для организации TCP сервера. Класс позволяет принимать запросы на соединение по протоколу TCP. При поступлении запрос становиться в очередь запросов. При желании сервера установить соединение, создаётся новый ip::tcp::socket и происходит установление соединения.
Ip::udp::socket – класс для организации датаграмного сокета. Предоставляет унифицированный интерфейс для работы с датаграмными сокетами.
Подробную работу с этими классами рассмотрим в пункте 1.4.2. и 1.4.3.
1.4.1.6. Классы ip::udp::endpoint и ip::tcp::endpoint
Для работы с IP адресами в библиотека Boost::Asio используется класс endpoint. Endpoin представляет собой связку адреса и порта.
Таблица 1.6
Конструктор |
basic_endpoint( |
|
|
const boost::asio::ip::address & addr, |
|
|
unsigned short port_num |
|
|
); |
|
Описание параметров |
addr –адрес конечной точки |
|
|
port_num – номер порта |
|
|
|
|
Для переопределения параметров используются функции: |
||
|
Таблица 1.7 |
|
|
|
|
Функция |
void address( |
|
|
const boost::asio::ip::address & addr |
|
|
); |
|
Описание функции |
Устанавливает адрес конечной точки |
|
Описание параметров |
addr –адрес конечной точки |
|
|
Таблица 1.8 |
|
|
|
|
Функция |
boost::asio::ip::address address() const; |
|
Описание функции |
Возвращает адрес конечной точки |
|
|
Таблица 1.9 |
|
|
|
|
Функция |
void port( |
|
|
unsigned short port_num |
|
|
); |
|
|
|
|
Описание функции |
Устанавливает порт конечной точки |
|
Описание параметров port_num –порт конечной точки
Таблица 1.10
Функция |
unsigned short port() const; |
Описание функции |
Возвращает порт конечной точки |