Boost.Asio:由于线程退出或应用程序请求,I/O 操作已中止
Boost.Asio: The I/O operation has been aborted because of either a thread exit or an application request
我在学习Boost.Asio。我创建了一个简单的程序来将主机名解析为 IP 地址。使用同步解析操作时它工作正常。但是,当我尝试异步方式时,出现了一些奇怪的行为。
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
using boost::asio::ip::tcp;
void resolver_handler(
const boost::system::error_code& err,
tcp::resolver::iterator it
) {
if (err) {
std::cerr << "Resolver error: " << err.message() << std::endl;
return;
}
tcp::resolver::iterator end;
while (it != end) {
std::cout << "Host name: " << it->host_name() << std::endl;
std::cout << "Endpoint: " << it->endpoint() << std::endl;
std::cout << "Service name: " << it->service_name() << std::endl;
++it;
}
}
void resolve_host(boost::asio::io_service& io_service) {
tcp::resolver::query query("www.google.com", "http");
tcp::resolver resolver(io_service);
resolver.async_resolve(
query,
boost::bind(
resolver_handler,
boost::asio::placeholders::error,
boost::asio::placeholders::iterator
)
);
std::cout << "Bind" << std::endl; // <<<----This line
}
int main(int argc, char **argv) {
try {
boost::asio::io_service io_service;
resolve_host(io_service);
io_service.run();
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
return 0;
}
当resolve_host
函数的最后一行被注释掉时,报告
Resolver error: The I/O operation has been aborted because of either a thread exit or an application request
当该行出现时,它会给出正确的输出
Bind
Host name: www.google.com
Endpoint: 216.58.219.4:80
Service name: http
我所做的是打印出一些东西。我试图在 async_resolve
调用之后添加一些更简单的逻辑,(例如 int a = 1;
),但它不起作用。在我看来,这是一个时间问题。也许有些东西退出得太快了。
我搜索此错误消息,但发现大多数帖子都是关于 C# 的。我相信此错误消息不是来自 Boost,而是来自 Windows 系统。
任何人都可以向我解释为什么会这样吗?非常感谢。
正如@David Schwartz 所说,您必须让解析器保持活动状态才能完成异步操作。
这是我能想到的最简单的方法:
void resolve_host(boost::asio::io_service& io_service) {
tcp::resolver::query query("www.google.com", "http");
auto resolver = std::make_shared<tcp::resolver>(io_service);
resolver->async_resolve(
query,
[resolver](auto ec, auto it) { resolver_handler(ec, it); }
);
}
注意我使用了 lambda 来捕获解析器(它是动态分配的而不是在堆栈上)。
如果您没有该选项,最简单的方法是将一些不透明的上下文绑定到完成处理程序中 bind
:
using opaque_context = std::shared_ptr<void const>;
void resolver_handler(
const boost::system::error_code& err,
tcp::resolver::iterator it,
opaque_context
) {
// ...
然后使用
resolver->async_resolve(
query,
boost::bind(resolver_handler, ph::error, ph::iterator, resolver)
);
同时查看 在 Coliru 上编译:c++03 only, C++11 opaque_context
, c++11 lambda
请注意,我可能会传递 endpoint
而不是 iterator
来进一步解耦代码(参见 ASIO getting a tcp endpoint directly from an asynchronous resolve). But you don't need to, because the iterator
does keep the associated state alive:
我在学习Boost.Asio。我创建了一个简单的程序来将主机名解析为 IP 地址。使用同步解析操作时它工作正常。但是,当我尝试异步方式时,出现了一些奇怪的行为。
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
using boost::asio::ip::tcp;
void resolver_handler(
const boost::system::error_code& err,
tcp::resolver::iterator it
) {
if (err) {
std::cerr << "Resolver error: " << err.message() << std::endl;
return;
}
tcp::resolver::iterator end;
while (it != end) {
std::cout << "Host name: " << it->host_name() << std::endl;
std::cout << "Endpoint: " << it->endpoint() << std::endl;
std::cout << "Service name: " << it->service_name() << std::endl;
++it;
}
}
void resolve_host(boost::asio::io_service& io_service) {
tcp::resolver::query query("www.google.com", "http");
tcp::resolver resolver(io_service);
resolver.async_resolve(
query,
boost::bind(
resolver_handler,
boost::asio::placeholders::error,
boost::asio::placeholders::iterator
)
);
std::cout << "Bind" << std::endl; // <<<----This line
}
int main(int argc, char **argv) {
try {
boost::asio::io_service io_service;
resolve_host(io_service);
io_service.run();
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
return 0;
}
当resolve_host
函数的最后一行被注释掉时,报告
Resolver error: The I/O operation has been aborted because of either a thread exit or an application request
当该行出现时,它会给出正确的输出
Bind
Host name: www.google.com
Endpoint: 216.58.219.4:80
Service name: http
我所做的是打印出一些东西。我试图在 async_resolve
调用之后添加一些更简单的逻辑,(例如 int a = 1;
),但它不起作用。在我看来,这是一个时间问题。也许有些东西退出得太快了。
我搜索此错误消息,但发现大多数帖子都是关于 C# 的。我相信此错误消息不是来自 Boost,而是来自 Windows 系统。
任何人都可以向我解释为什么会这样吗?非常感谢。
正如@David Schwartz 所说,您必须让解析器保持活动状态才能完成异步操作。
这是我能想到的最简单的方法:
void resolve_host(boost::asio::io_service& io_service) {
tcp::resolver::query query("www.google.com", "http");
auto resolver = std::make_shared<tcp::resolver>(io_service);
resolver->async_resolve(
query,
[resolver](auto ec, auto it) { resolver_handler(ec, it); }
);
}
注意我使用了 lambda 来捕获解析器(它是动态分配的而不是在堆栈上)。
如果您没有该选项,最简单的方法是将一些不透明的上下文绑定到完成处理程序中 bind
:
using opaque_context = std::shared_ptr<void const>;
void resolver_handler(
const boost::system::error_code& err,
tcp::resolver::iterator it,
opaque_context
) {
// ...
然后使用
resolver->async_resolve(
query,
boost::bind(resolver_handler, ph::error, ph::iterator, resolver)
);
同时查看 在 Coliru 上编译:c++03 only, C++11 opaque_context
, c++11 lambda
请注意,我可能会传递 endpoint
而不是 iterator
来进一步解耦代码(参见 ASIO getting a tcp endpoint directly from an asynchronous resolve). But you don't need to, because the iterator
does keep the associated state alive: