解析查询和创建具有IP和端口的端点(在boost asio中)之间的区别

Difference between resolving a query and creating an endpoint with IP and port (in boost asio)

本文关键字:boost asio 区别 之间 端点 创建 查询 IP      更新时间:2023-10-16

我最近注意到我的应用程序出现了一个问题,我认为这是由于我没有正确使用boost::asio,也不了解tcp解析器的作用。

基本上,我使用boost::asio::ip::tcp::resolver来获取要连接的端点。

我最近发现,它可以产生多个端点(尤其是当我连接到localhost时)。

目前,我请求在所有端点上使用async_connect。我不能百分之百肯定,但我认为这很糟糕。我应该一个接一个地向他们请求async_connect,等待回复,并在失败的情况下尝试下一个。

所以基本上知道,如果我想在这些端点上使用async_connect,我有两个选择:

  1. 重构我的代码,使我的async_connect能够正确处理故障,并在故障时尝试连接到其他可用的端点。然后我必须通过端点迭代器。

  2. 删除解析器并使用我自己构造的端点:boost::asio::ip::tcp::endpoint("localhost", 20015)

我有一种感觉,我应该使用第一个解决方案,解析器带来的不仅仅是自建端点。

但是,解析器带来了什么?自行构建的端点如何自行解决它?

虽然Sam简洁地回答了大多数应用程序如何处理端点创建,但我想扩展resolver

resolver用于通过主机名解析或定义的表示之间的转换,将地址的人类可读文本表示转换为包含地址的结构化二进制格式的endpoint。例如,resolver可以将人类可读的"localhost"解析为0x7F000001或者将"127.0.0.1"转换为0x7F000001。Boost.Asio使用或模拟getaddrinfo()来执行此分辨率。对于异步解析,将创建一个内部线程来执行操作。

另一方面,basic_endpoint不会自行解析。虽然它不能用字符串和端口构造,但它可以用ip::address和端口构造。ip::address可以用点十进制(IPv4)或十六进制表示法(IPv6)的字符串构造:

namespace ip = boost::asio::ip;
ip::tcp::endpoint(ip::address::from_string("127.0.0.1"), 20015);

ip::address::from_string()提供主机名将引发异常:

namespace ip = boost::asio::ip;
ip::address::from_string("localhost"); // throws boost::system::system_error

最后,使用:

  • resolver,当您希望支持主机名解析或IP转换时。当IP可能更改但主机名保持不变时,或者当单个主机名可能解析为多个IP时,这尤其方便
  • CCD_ 21从IP创建地址

您正确地认为,连接到解析操作返回的所有端点不太可能是您的应用程序所期望的。选择#2将不起作用,因为basic_endpoint(const char*, int)没有构造函数。选择#1是几个asio示例的结构,特别是演示超时的异步tcp客户端。

重构代码以包含解析程序返回的endpoint_iterator应该不会太困难,如果遇到问题,请按照上面的示例进行操作。请注意,它使用了阻塞resolve()而不是async_resolve(),但是概念是相同的。