@john-lee
2021-01-03T07:52:28.000000Z
字数 2463
阅读 647
Boost.Asio
Boost.Asio 对互联网协议 TCP、UDP 和 ICMP 提供现成的支持。
主机名解析使用解析程序执行,在解析程序中查找主机名和服务名并将其转换为一个或多个端点(endpoint):
ip::tcp::resolver resolver(my_io_context);
ip::tcp::resolver::query query("www.boost.org", "http");
ip::tcp::resolver::iterator iter = resolver.resolve(query);
ip::tcp::resolver::iterator end; // End marker.
while (iter != end)
{
ip::tcp::endpoint endpoint = *iter++;
std::cout << endpoint << std::endl;
}
上面获得的端点列表可能同时包含 IPv4 和 IPv6 端点,因此程序应该尝试其中的每一个端点,直到找到一个有效的端点为止。这使得客户端程序独立于特定的 IP 版本。
为了简化与协议无关的程序的开发,TCP 客户端可以使用自由函数connect()
和async_connect()
建立连接。这些操作将尝试列表中的每个端点,直到成功连接套接字。例如,单个调用:
ip::tcp::socket socket(my_io_context);
boost::asio::connect(socket, resolver.resolve(query));
将同步尝试所有端点,直到成功连接一个端点。同样,异步连接可以这样写:
boost::asio::async_connect(socket_, iter,
boost::bind(&client::handle_connect, this,
boost::asio::placeholders::error));
// ...
void handle_connect(const error_code& error)
{
if (!error)
{
// Start read or write operations.
}
else
{
// Handle error.
}
}
当特定端点可用时,可以创建并连接套接字:
ip::tcp::socket socket(my_io_context);
socket.connect(endpoint);
可以使用receive()
、async_receive()
成员函数从连接的 TCP 套接字读取数据或用send()
、async_send()
成员函数向其写入数据。但是,由于这样做可能导致短写或短读,因此应用程序通常会改用以下操作:read()
,async_read()
,write()
和async_write()
。
程序使用接受器接受传入的 TCP 连接:
ip::tcp::acceptor acceptor(my_io_context, my_endpoint);
...
ip::tcp::socket socket(my_io_context);
acceptor.accept(socket);
成功接受套接字后,可以从中读取或写入,如上面的TCP客户端所示。
UDP 主机名解析也使用解析器执行:
ip::udp::resolver resolver(my_io_context);
ip::udp::resolver::query query("localhost", "daytime");
ip::udp::resolver::iterator iter = resolver.resolve(query);
...
UDP 套接字通常绑定到本地端点。以下代码将创建IP 版本 4 的 UDP 套接字并将其绑定到端口 12345 上的“any”地址:
ip::udp::endpoint endpoint(ip::udp::v4(), 12345);
ip::udp::socket socket(my_io_context, endpoint);
使用receive_from()
,async_receive_from()
成员函数从未连接的 UDP 套接字读取数据或用send_to()
、async_send_to()
成员函数向其写入数据。对于已连接的 UDP 套接字,请使用receive()
,async_receive()
,send()
或async_send()
成员函数。
与 TCP 和 UDP 一样,使用解析器执行 ICMP 主机名解析:
ip::icmp::resolver resolver(my_io_context);
ip::icmp::resolver::query query("localhost", "");
ip::icmp::resolver::iterator iter = resolver.resolve(query);
...
ICMP 套接字可以绑定到本地端点。以下代码将创建 IP 版本 6 的 ICMP 套接字并将其绑定到“any”地址:
ip::icmp::endpoint endpoint(ip::icmp::v6(), 0);
ip::icmp::socket socket(my_io_context, endpoint);
端口号不用于 ICMP。
可以使用receive_from()
、async_receive_from()
成员函数从未连接的 ICMP 套接字读取数据或用send_to()
、async_send_to()
成员函数向其写入数据。
ip::tcp, ip::udp, ip::icmp,daytime 协议教程,ICMP ping 示例。
Copyright © 2003-2020 Christopher M. Kohlhoff
Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)