Boost.Asio是一个异步编程的网络框架, 核心的优势在于IO操作的异步调用. 异步调用时, 会用到boost::asio::io_context::run()
函数, 这个函数表示启动一个IO的异步循环, 与该io_context
有关的回调函数, 会在该io_context
所在的线程中运行, 举个代码的例子:
#include <boost/asio.hpp>
#include <iostream>
#include <chrono>
#include <string>
#include <thread>
int main() {
std::string raw_ip_addr = "127.0.0.1";
unsigned int port = 6768;
boost::asio::ip::tcp::endpoint ep(
boost::asio::ip::address::from_string(raw_ip_addr),
port
);
boost::asio::io_context ioc1, ioc2;
boost::asio::ip::tcp::socket sock1(ioc1, ep.protocol()), sock2(ioc2, ep.protocol());
sock1.async_connect(ep, [](const boost::system::system_error &ec) {
std::cout << "sock1 async_connect, thread id: " << std::this_thread::get_id() << "\n";
if (ec.code()) {
std::cout << ec.what() << std::endl;
}
});
sock2.async_connect(ep, [](const boost::system::system_error &ec) {
std::cout << "sock2 async_connect, thread id: " << std::this_thread::get_id() << "\n";
if (ec.code()) {
std::cout << ec.what() << std::endl;
}
});
std::this_thread::sleep_for(std::chrono::seconds(1));
std::thread t1([&ioc1](){
try {
ioc1.run();
} catch (boost::system::system_error& e) {
std::cout << "Error :" << e.what() << std::endl;
}
});
std::thread t2([&ioc2](){
try {
ioc2.run();
} catch (boost::system::system_error& e) {
std::cout << "Error :" << e.what() << std::endl;
}
});
std::this_thread::sleep_for(std::chrono::milliseconds(100));
t1.join();
t2.join();
return 0;
}
一种可能的输出结果:
sock1 async_connect, thread id: 139979035465472
Connection refused
sock2 async_connect, thread id: 139979027072768
Connection refused
可以明显看出, 是两个不同的事件循环, 运行在不同的线程中.
因此得出的结论是, boost::asio::io_context::run()
表示一个异步的事件循环, 使用同一个io_contex
的读写对象, 那么异步操作会在同一个线程中按照IO完成的先后顺序执行, io_context::run()
表示启动事件循环, 之后发生io完成回调便会执行. 在实际的编程中, 只需要在不同的线程执行run()
函数, 那么事件就会在指定的线程执行.