
😎 作者介绍:欢迎来到我的主页👈,我是程序员行者孙,一个热爱分享技术的制能工人。计算机本硕,人工制能研究生。公众号:AI Sun(领取大厂面经等资料),欢迎加我的微信交流:sssun902
🎈 本文专栏:本文收录于《Asio网络编程》系列专栏,相信一份耕耘一份收获,我会分享Asio网络编程相关学习内容,不说废话,祝大家都offer拿到手软
🤓 欢迎大家关注其他专栏,我将分享Web前后端开发、人工智能、机器学习、深度学习从0到1系列文章。
🖥随时欢迎您跟我沟通,一起交流,一起成长、进步!
asio协程实现并发服务器
定义协程函数
协程函数的返回类型为boost::asio::awaitable,其中T是协程的返回值类型。例如,一个返回类型为void的协程可以这样定义:
boost::asio::awaitable<void> my_coroutine() {
// 协程逻辑
}
co_await挂起协程
co_await是C++20协程的关键字,用于挂起当前协程,直到等待的操作完成。例如,异步读取操作可以这样写:
std::size_t n = co_await socket.async_read_some(boost::asio::buffer(data), boost::asio::use_awaitable);
启动协程
boost::asio::co_spawn(ioc, my_coroutine, boost::asio::detached);
主要涉及上面的操作,协程是C++20改进提出的,在visual studio中需要改一下版本支持。
定义 echo 协程函数
awaitable<void> echo(tcp::socket socket) {
try {
char data[1024];
for (;;) {
std::size_t n = co_await socket.async_read_some(boost::asio::buffer(data), use_awaitable);
if (n == 0) break; // Connection closed cleanly by peer.
co_await boost::asio::async_write(socket, boost::asio::buffer(data, n), use_awaitable);
}
} catch (std::exception& e) {
std::cout << "Exception: " << e.what() << std::endl;
}
}
echo是一个返回类型为awaitable<void>的协程,用于处理与客户端的通信。- 它进入一个无限循环,等待从客户端读取数据。
- 每当读取到数据时(
n > 0),它会将相同的数据写回到客户端,实现回显功能。 - 如果读取到的数据长度为0 (
n == 0),表示客户端关闭了连接,则退出循环。 - 如果在读写过程中遇到异常,会在捕获异常后打印错误信息。
定义 listener 协程函数
awaitable<void> listener() {
auto executor = co_await boost::asio::this_coro::executor;
tcp::acceptor acceptor(executor, {tcp::v4(), 8888});
while (true) {
tcp::socket socket = co_await acceptor.async_accept(use_awaitable);
co_spawn(executor, echo(std::move(socket)), detached);
}
}
listener是一个返回类型为awaitable<void>的协程,负责监听新的客户端连接。- 它首先获取当前协程的执行器(
executor),然后创建一个TCP接受者(acceptor),绑定到IPv4地址的8888端口上。 - 接下来进入一个无限循环,等待新的连接请求。
- 当有新连接到来时,它会异步地接受这个连接,并启动一个新的
echo协程来处理该连接。 - 使用
co_spawn来启动新的echo协程,并传入detached表示不关心协程的结果。
main 函数:程序入口点
int main() {
try {
boost::asio::io_context ioc;
co_spawn(ioc, listener, detached);
ioc.run();
} catch (const std::exception& e) {
std::cout << e.what() << std::endl;
}
return 0;
}
- 在
main函数中,首先创建了一个io_context对象ioc,它是事件循环的核心,所有的异步操作都依赖于它。 - 然后调用
co_spawn启动listener协程,同样使用detached标志。 - 最后调用
ioc.run()启动事件循环,开始处理所有挂起的异步操作。 - 如果在事件循环中发生任何未捕获的异常,它们会被
main函数中的catch块捕获并打印出来。
流程总结
- 初始化:程序启动时,
main函数创建io_context并启动listener协程。 - 监听连接:
listener协程在指定端口监听新的连接请求。 - 处理连接:每当有一个新的连接到来时,
listener协程就会启动一个新的echo协程来处理这个连接。 - 回显数据:每个
echo协程会接收来自客户端的数据并将其发送回去,直到连接被关闭。 - 异常处理:在整个过程中,无论是
listener还是echo协程,都会进行适当的异常处理,确保程序能够稳定运行。 - 事件循环:
io_context的run方法会一直运行,直到没有更多的工作需要处理或遇到异常为止。
通过这种方式,服务器可以高效地并发处理多个客户端连接,同时保持代码的简洁性和可读性。
祝大家学习顺利~
如有任何错误,恳请批评指正~~
以上是我通过各种方式得出的经验和方法,欢迎大家评论区留言讨论呀,如果文章对你们产生了帮助,也欢迎点赞收藏,我会继续努力分享更多干货~
🎈关注我的公众号AI Sun可以获取Chatgpt最新发展报告以及腾讯字节等众多大厂面经。
😎也欢迎大家和我交流,相互学习,提升技术,风里雨里,我在等你~

353

被折叠的 条评论
为什么被折叠?



