我最近注意到我的应用程序存在问题,我认为这是因为我没有正确使用boost::asio
并且不了解tcp解析器的作用。
基本上,我使用boost::asio::ip::tcp::resolver
来获取要连接的端点。
我最近发现的是它可以提供多个端点(特别是当我连接到localhost时)。
目前我在所有终点上请求async_connect
。我不是100%肯定,但我认为这很糟糕。我应该逐个向他们请求async_connect,等待回复并尝试下一个,当且仅当它失败时。
基本上知道如果我想在这些终点上使用async_connect
,我有两个选择:
重构我的代码,以便我的async_connect
正确处理失败并在失败时尝试连接到其他可用端点。我必须传递端点迭代器。
删除解析器并使用我自己构建的端点:boost::asio::ip::tcp::endpoint("localhost", 20015)
我有种感觉,我应该使用第一个解决方案,并且解析器带来的东西比自构造的端点更多。
但解析器会带来什么,以及自构建端点如何解决它?
答案 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()
,但概念是相同的。