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

时间:2013-07-03 07:32:15

标签: c++ boost tcp boost-asio

我最近注意到我的应用程序存在问题,我认为这是因为我没有正确使用boost::asio并且不了解tcp解析器的作用。

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

我最近发现的是它可以提供多个端点(特别是当我连接到localhost时)。

目前我在所有终点上请求async_connect。我不是100%肯定,但我认为这很糟糕。我应该逐个向他们请求async_connect,等待回复并尝试下一个,当且仅当它失败时。

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

  1. 重构我的代码,以便我的async_connect正确处理失败并在失败时尝试连接到其他可用端点。我必须传递端点迭代器。

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

  3. 我有种感觉,我应该使用第一个解决方案,并且解析器带来的东西比自构造的端点更多。

    但解析器会带来什么,以及自构建端点如何解决它?

2 个答案:

答案 0 :(得分:15)

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

resolver用于将地址的人类可读文本表示转换为endpoint(s),其中包含通过hostname resolution的地址的结构化二进制格式或定义的表示之间的转换。例如,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时,这尤其方便。
  • ip::address::from_string()从IP创建地址。

答案 1 :(得分:6)

您是正确的,连接到解析操作返回的所有端点可能不是您的应用程序所期望的。选择#2不起作用,因为basic_endpoint(const char*, int)没有构造函数。选择#1是几个asio示例的结构,特别是async tcp client demonstrating timeouts

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