我在 SNMPV2 实现中使用 boost::asio::ip::udp::resolver 来确定主机是否可访问。
using Resolver = boost::asio::ip::udp::resolver;
Resolver resolver(ioService);
Resolver::query query(connectOptions.getHost(),
connectOptions.getPort());
Resolver::iterator endpointIterator;
BOOST_LOG_SEV(logger, Severity::debug) << "Waiting for async resolve";
endpointIterator = resolver.async_resolve(query, yield);
BOOST_LOG_SEV(logger, Severity::debug) << "Async resolve done";
if (endpointIterator == Resolver::iterator{}) { // unreachable host
using namespace boost::system;
throw system_error{error_code{SnmpWrapperError::BadHostname}};
}
我有一个测试用例,我在其中测试并行查询不存在的主机名和现有主机名时发生的情况:
2013-09-16 10:45:28.687001: [DEBUG ] 0x88baf8 SnmpConnection: connect
2013-09-16 10:45:28.687396: [DEBUG ] 0x88baf8 SnmpConnection: host: non_existent_host_name_
2013-09-16 10:45:28.687434: [DEBUG ] 0x88baf8 SnmpConnection: port: 1611
2013-09-16 10:45:28.687456: [DEBUG ] 0x88baf8 SnmpConnection: Waiting for async resolve
2013-09-16 10:45:28.687675: [DEBUG ] 0x88c608 SnmpConnection: connect
2013-09-16 10:45:28.687853: [DEBUG ] 0x88c608 SnmpConnection: host: 127.0.0.1
2013-09-16 10:45:28.687883: [DEBUG ] 0x88c608 SnmpConnection: port: 1611
2013-09-16 10:45:28.687904: [DEBUG ] 0x88c608 SnmpConnection: Waiting for async resolve
2013-09-16 10:45:31.113527: [ERROR ] 0x88baf8 SnmpConnection: Host not found (authoritative)
2013-09-16 10:45:31.113708: [DEBUG ] 0x88c608 SnmpConnection: Async resolve done
2013-09-16 10:45:31.113738: [DEBUG ] 0x88c608 SnmpConnection: Connecting to 127.0.0.1:1611
...
从日志可以看出,具有可达地址的对象被阻塞,直到另一个人的解析完成并出现错误(3秒)。我的假设是 Asio 解析器服务使用一个线程,因此对一台无法访问的主机的一次查询可能会阻止对即将到来的解析请求的处理。
解决方法是在更多线程上运行解析器服务,这可能吗?或者是否有可能拥有像 udp 服务一样在套接字上工作的解析器服务(而不是使用 ::getaddrinfo)?