1. asio::io_context
asio::io_context表示io的上下文,任何io都会涉及到一个io_context。
同步io会隐式地启动一个io_context, 而异步io需要我们指定一个io_context。
调用run()函数进入io事件循环。如果有io事件,事件完成会调用回调函数; 如果没有io事件, io_context会自动取消事件循环。
int main()
{
asio::io_context ioc;
asio::ip::tcp::endpoint ep(asio::ip::address::from_string("127.0.0.1"), 6768);
asio::ip::tcp::socket sock(ioc, ep.protocol());
asio::ip::tcp::socket sock1(ioc, ep.protocol());
sock.async_connect(ep, [](const std::error_code & err) {
if (err.value() != 0) {
std::cout << "Error: "<< err.message() << std::endl;
}
});
sock1.async_connect(ep, [](const std::error_code & err) {
if (err.value() != 0) {
std::cout << "Error: "<< err.message() << std::endl;
}
});
ioc.run();
getchar();
return 0;
}
执行结果:
调整语句ioc.run()的位置,置于两个async_connect()之间。
sock.async_connect(ep, [](const std::error_code & err) {
if (err.value() != 0) {
std::cout << "Error: "<< err.message() << std::endl;
}
});
ioc.run();
// 这个回调函数不会执行了, 因为run的事件循环已经结束了
sock1.async_connect(ep, [](const std::error_code & err) {
if (err.value() != 0) {
std::cout << "Error: "<< err.message() << std::endl;
}
});
执行结果:
2.asio::io_context::work
有时候, 我们希望调用run()后,即使没有io
事件, 也不会退出事件循环, 而是一直等待, 当有了新的异步io调用的时候, 还可以继续使用该循环。 asio::io_context::work
可以防止io_context
在没有io事件的情退出。
int main()
{
asio::io_context ioc;
asio::ip::tcp::endpoint ep(asio::ip::address::from_string("127.0.0.1"), 6768);
asio::ip::tcp::socket sock(ioc, ep.protocol());
asio::ip::tcp::socket sock1(ioc, ep.protocol());
asio::io_context::work worker(ioc);
std::thread t([&ioc]() {ioc.run(); });
sock.async_connect(ep, [](const std::error_code & err) {
if (err.value() != 0) {
std::cout << "Error: " << err.message() << std::endl;
}
});
sock1.async_connect(ep, [](const std::error_code & err) {
if (err.value() != 0) {
std::cout <<"Error: "<< err.message() << std::endl;
}
});
std::cout << "Main thread will for 3 seconds...\n"; // 防止stop()执行过快
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "Main thread weak up...\n";
ioc.stop(); // 显式停止io_context, 否则无法终止
t.join();
return 0;
}
执行结果:
注释掉语句asio::io_context::work worker(ioc)后。
执行结果:
即事件循环在没有IO事件的情况下, 就自动结束了。
3.总结
在不确定io异步事件回调发生的情况下, 如果想要io_context
事件循环一直进行, 就要使用io_context::work对象
来执行。