Daytime.1 - A synchronous TCP daytime client
https://www.boost.org/doc/libs/1_74_0/doc/html/boost_asio/tutorial/tutdaytime1.html
Daytime.1 - A synchronous TCP daytime client
这次的教程演示一下怎么用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的程序都至少得有一个execution context的对象,比如我们整的这个io_context类对象.
boost::asio::io_context io_context;
为了把从参数读进来的服务器地址转换为一个TCP endpoint(TCP端点),我们得需要一个ip::tcp::resolver对象.
tcp::resolver resolver(io_context);
一个resolver可以把一个主机和服务器地址转为一个端点列表.我们把arg[1]里传进来的服务器地址交给resolver去resolve(可能是解析的意思)一下(此处为daytime).
返回的端点列表放在一个类型为ip::tcp::resolver::results_type的对象里.这是一个有begin(),end()迭代器的范围对象,可以用迭代器来遍历里面的东西.
tcp::resolver::results_type endpoints =
resolver.resolve(argv[1], "daytime");
现在让我们去创建和连接socket.我们上面拿到的endpoints列表里面可能既有 IPv4 也有 IPv6 的端点,那我们就得挨个试,直到找到一个能用的为止.这样做的好处是能客户端不依赖于IP版本.函数boost::asio::connect()自动帮我们把这个活给干了.
tcp::socket socket(io_context);
boost::asio::connect(socket, endpoints);
连接打开了.我们现在需要做的就是从daytime服务器上读取响应内容了.
我们搞一个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()会以boost::asio::error::eof退出,这样我们就知道该退出循环了.
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;
}
}
回顾一下整体的代码
#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;
}
boost::asio::io_context io_context;
tcp::resolver resolver(io_context);
tcp::resolver::results_type endpoints =
resolver.resolve(argv[1], "daytime");
tcp::socket socket(io_context);
boost::asio::connect(socket, endpoints);
for (;;)
{
boost::array<char, 128> buf;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error); // Some other error.
std::cout.write(buf.data(), len);
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
Daytime.1 - A synchronous TCP daytime client
https://www.boost.org/doc/libs/1_74_0/doc/html/boost_asio/tutorial/tutdaytime1.html