Эта учебная программа показывает, как использовать Asio для реализации клиентского приложения с TCP.
Мы начинаем с включения необходимых файлов заголовка.
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
Целью этого приложения является доступ к дневному сервису, поэтому пользователю необходимо указать сервер.
using boost::asio::ip::tcp;
int main(int argc, char* argv[])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: client <host>" << std::endl;
return 1;
}
Все программы, использующие Asio, должны иметь хотя бы один объект io_service.
boost::asio::io_service io_service;
Нам нужно превратить имя сервера, которое было указано в качестве параметра, в конечную точку TCP. Для этого мы используем объект ip::tcp::resolver.
tcp::resolver resolver(io_service);
Решитель берет объект запроса и превращает его в список конечных точек. Мы создаем запрос, используя имя сервера, указанное в argv[1]
, и имя сервиса, в данном случае "дневное время"
.
tcp::resolver::query query(argv[1], "daytime");
Список конечных точек возвращается с помощью итератора типа ip::tcp::resolver::iterator. (Обратите внимание, что по умолчанию построен ip::tcp::resolver::iterator Объект можно использовать как конечный итератор
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
Теперь создаем и подключаем розетку. Список конечных точек, полученных выше, может содержать как конечные точки IPv4, так и конечные точки IPv6, поэтому мы должны попробовать каждую из них, пока не найдем ту, которая работает. Это позволяет сохранить клиентскую программу независимой от конкретной IP-версии. Функция boost::asio::connect() делает это автоматически.
tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
Связь открыта. Все, что нам нужно сделать сейчас, это прочитать ответ от дневной службы.
Мы используем boost::array
для хранения полученных данных. Функция boost::asio::buffer() автоматически определяет размер массива, чтобы предотвратить переполнение буфера. Вместо boost::array
мы могли бы использовать char []
или std::vector
.
for (;;)
{
boost::array<char, 128> buf;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);
Когда сервер закроет соединение, функция ip::tcp::socket::read_some() выйдет с повышением::asio::error::eof error, то есть как мы знаем, чтобы выйти из цикла.
if (error == boost::asio::error::eof)
break;
else if (error)
throw boost::system::system_error(error);
std::cout.write(buf.data(), len);
}
Наконец, обращайтесь с любыми исключениями, которые могли быть сделаны.
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
См. полный список источников
Вернуться в tutorial index
Daytime.2 - синхронный дневной сервер TCP