下面是一个使用ASIO正确处理多线程、strand、socket和timer的代码示例:
#include
#include
#include
#include
using namespace std;
void workerThread(asio::io_context& ioContext) {
ioContext.run();
}
void printThreadId() {
cout << "Thread ID: " << this_thread::get_id() << endl;
}
void printMessage(const string& message) {
printThreadId();
cout << message << endl;
}
void handleTimer(const asio::error_code& error, asio::steady_timer* timer) {
if (error) {
printMessage("Timer error: " + error.message());
return;
}
printMessage("Timer expired");
timer->expires_after(chrono::seconds(1));
timer->async_wait([timer](const asio::error_code& error) {
handleTimer(error, timer);
});
}
void handleRead(const asio::error_code& error, size_t bytesTransferred) {
if (error) {
printMessage("Read error: " + error.message());
return;
}
printMessage("Received message: " + string(buffer.data(), bytesTransferred));
}
void startRead(asio::ip::tcp::socket& socket) {
asio::async_read(socket, asio::buffer(buffer), asio::transfer_at_least(1),
asio::bind_executor(strand, bind(handleRead, std::placeholders::_1, std::placeholders::_2)));
}
void handleAccept(asio::ip::tcp::socket& socket, asio::io_context& ioContext) {
printMessage("Accepted connection");
startRead(socket);
asio::ip::tcp::socket newSocket(ioContext);
acceptor.async_accept(newSocket, bind(handleAccept, ref(newSocket), ref(ioContext)));
}
int main() {
asio::io_context ioContext;
asio::io_context::strand strand(ioContext);
asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 8888);
asio::ip::tcp::acceptor acceptor(ioContext, endpoint);
asio::steady_timer timer(ioContext);
timer.expires_after(chrono::seconds(1));
timer.async_wait([&timer](const asio::error_code& error) {
handleTimer(error, &timer);
});
vector threads;
for (int i = 0; i < thread::hardware_concurrency(); ++i) {
threads.emplace_back([&ioContext]() {
workerThread(ioContext);
});
}
printMessage("Server started");
asio::ip::tcp::socket socket(ioContext);
acceptor.async_accept(socket, bind(handleAccept, ref(socket), ref(ioContext)));
for (auto& thread : threads) {
thread.join();
}
return 0;
}
在这个示例中,首先创建了一个asio::io_context
对象和一个asio::io_context::strand
对象。然后,创建了一个asio::ip::tcp::acceptor
对象来侦听客户端连接。接下来,创建一个asio::steady_timer
对象来定期触发操作。然后,创建了多个工作线程,每个线程都运行workerThread
函数,其中调用ioContext.run()
来执行IO操作。
在handleAccept
函数中,当有新的客户端连接时,会打印一条消息,并启动一个异步读操作startRead
来读取客户端发送的数据。在startRead
函数中,使用asio::async_read
函数来异步读取数据,并使用asio::bind_executor
来绑定strand
对象,以确保在同一线程中处理读取操作。
在handleRead
函数中,当读操作完成时,会打印接收到的消息。
在handleTimer
函数中,当定时器超时时,会打印一条消息,并重新启动定时器。
最后,在main
函数中,创建了多个工作线程,并启动ioContext.run()
来执行IO操作。然后,创建一个asio::ip::tcp::socket
对象,并使用acceptor.async_accept
函数异步接受客户端连接。最后,等待工作线程结束,并返回0。
上一篇:ASIO异步写入空缓冲区
下一篇:ASIO中的协程通信