【C++boost::asio网络编程】使用asio协程搭建异步echo服务器的笔记

【C++boost::asio网络编程】使用asio协程搭建异步服务器的笔记

协程和线程关系以及线程和进程的关系简单区分

资源消耗与开销

  • 进程与线程:
    • 进程 是操作系统分配资源的基本单位,每个进程拥有自己的内存空间、文件描述符等资源。
    • 线程 是进程中的执行单元,同一个进程中的多个线程共享进程的资源(如内存空间、文件描述符等)。线程的创建和上下文切换相对于进程来说,开销较小,但仍然需要操作系统的支持。
  • 协程与线程:
    • 协程 是一种轻量级的用户级执行单元,它与线程相比,具有更小的资源开销。多个协程通常运行在一个线程中,共享线程的资源(如 CPU 时间、内存等)。
    • 线程 是操作系统调度的基本单元,协程是在用户级别进行调度的,它并不依赖操作系统进行上下文切换。因此,协程的切换和调度开销比线程小得多。

调度与上下文切换

  • 进程与线程:
    • 进程线程 的调度通常由操作系统管理,线程的上下文切换涉及到保存和恢复 CPU 寄存器、内存映射等状态。
    • 线程切换 的开销比进程切换小,但仍然需要操作系统的干预。
  • 协程与线程:
    • 协程 的调度通常是由程序自身管理的,协程的上下文切换不需要操作系统的参与,通常只是通过保存和恢复少量的状态(例如局部变量、程序计数器等)来完成。因此,协程的上下文切换比线程切换的开销更小。

并发性

  • 进程与线程:
    • 进程 之间是完全独立的,一个进程的崩溃不会直接影响到其他进程。
    • 线程 之间是并发的,在同一进程中可以并行执行多个线程(在多核 CPU 上,多个线程可以真正地并行运行),但是它们会共享进程的资源。
  • 协程与线程:
    • 协程 是轻量级的并发单元,它们运行在单个线程中。多个协程可以在同一个线程中并发执行,但它们并不会并行执行(即不会在多个 CPU 核心上同时运行)。协程通过协作式调度来实现并发,通常在 I/O 操作或者其他需要等待的地方挂起,给其他协程执行的机会。

独立性

  • 进程与线程:
    • 进程 是独立的,通常不会直接共享内存等资源,进程间的通信需要通过特定的机制(如管道、消息队列、共享内存等)。
    • 线程 共享进程的内存空间,可以直接访问共享数据,因此线程之间的通信较为方便,但也需要注意同步问题。
  • 协程与线程:
    • 协程 不独立,它们共享同一个线程的资源。多个协程之间的切换不会涉及到线程的上下文切换,只是在协程之间的切换。协程之间通常通过共享内存来通信,但也需要小心避免并发问题。

main函数

cpp 复制代码
int main()
{
	try
	{
		boost::asio::io_context ioc;
		boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);
		signals.async_wait([&](auto, auto) {
			ioc.stop();
			});
		boost::asio::co_spawn(ioc, listener, boost::asio::detached);
		ioc.run();
	}
	catch (const std::exception& e)
	{
		std::cout << e.what() << std::endl;
	}
	return 0;
}
cpp 复制代码
boost::asio::co_spawn(ioc, listener, boost::asio::detached);

这段代码的主要功能是启动一个新的协程来运行listener函数(这个函数用来监听来自客户端的连接),

listener函数

cpp 复制代码
boost::asio::awaitable<void> listener()
{
	auto executor = co_await boost::asio::this_coro::executor;
	boost::asio::ip::tcp::acceptor acceptor(executor, { boost::asio::ip::tcp::v4(),8888 });
	while (true)
	{
		boost::asio::ip::tcp::socket socket = co_await acceptor.async_accept(boost::asio::use_awaitable);
		boost::asio::co_spawn(executor, echo(std::move(socket)), boost::asio::detached);
	}
}
cpp 复制代码
boost::asio::awaitable<void> listener()

首先来介绍一下这个返回值为什么要这么写:boost::asio::awaitable<T>是一种协程返回类型,表示该函数返回的是一个可以挂起的协程
什么叫做返回一个可以挂起的协程?

这个意思就是说该函数返回的对象能在某个点暂停执行,等待某个操作(例如异步IO,网络请求等)完成后再继续执行,这种特性是现代协程模型中的核心概念。在C++20中,协程通过co_await,co_return等关键字来实现,例如co_await用于挂起当前协程并等待一个异步操作完成。

而挂起指的是协程在执行过程中暂停下来,等待某些条件或操作完成,这时,协程将不会占用CPU,其他任务可以继续执行,直到挂起的操作完成之后,该协程才会恢复执行

cpp 复制代码
auto executor = co_await boost::asio::this_coro::executor;

这段代码就是用来获取当前协程所在的"执行上下文"。在Boost::asio中,executor是一个对象,主要负责调度和执行任务,它是io_context或io_service的一部分,确保异步任务能够执行。

co_await是一个协程操作符,它用户挂起当前协程,直到等待的对象完成.通过co_wait,协程不会立即返回,而是将控制权交还给调用者,直到获取到执行器对象为止。

cpp 复制代码
boost::asio::ip::tcp::socket socket = co_await acceptor.async_accept(boost::asio::use_awaitable);

async_accept中的参数boost::asio::use_awaitable的主要作用是使得async_accept能够与C++20的协程机制兼容,在这段代码中,它使得async_accept返回的是一个C++20 协程机制交互的"协程兼容对象",能够在异步操作完成时继续执行

cpp 复制代码
boost::asio::co_spawn(executor, echo(std::move(socket)), boost::asio::detached);

这行代码的意思是启动一个协程。第一个参数是一个执行器对象,用户控制协程的上下文。第二个参数是socket对象,表示创建的协程通过这个对象为客户端进行服务,第三个参数的作用是表示不需要关心启动的这个协程完成的情况。

echo函数

cpp 复制代码
boost::asio::awaitable<void> echo(boost::asio::ip::tcp::socket socket)
{
	try
	{
		char data[1024];
		while (true)
		{
			size_t n = co_await socket.async_read_some(boost::asio::buffer(data), boost::asio::use_awaitable);
			std::cout << "写回去" << std::endl;
			co_await boost::asio::async_write(socket, boost::asio::buffer(data, n), boost::asio::use_awaitable);
		}
	}
	catch (const std::exception& e)
	{
		std::cout << e.what() << std::endl;
	}
}

echo函数的作用就是接收客户端发过来的信息然后转发回去,实现一个简单的echo server服务器。

相关推荐
xsh801442421 小时前
HTTP 范围Range请求
网络·网络协议·http
JovaZou2 小时前
[Python学习日记-75] 计算机基础与网络
开发语言·网络·python·网络协议·学习·tcp/ip·计算机网络
KeyPan3 小时前
【Ubuntu与Linux操作系统:十、C/C++编程】
linux·运维·服务器·c语言·c++·算法·ubuntu
计算机毕设定制辅导-无忧学长3 小时前
HTTP 入门:认识网络通信基础
网络·网络协议·http
陌上花开缓缓归以4 小时前
linux 内核OOM问题定位-SLAB_DEBUG
linux·运维·服务器
努力的小T4 小时前
Linux 搭建 Docker 私有化仓库 Harbor 教程
linux·运维·服务器·docker·云原生·容器·云计算
大丈夫立于天地间5 小时前
OSPF - 特殊报文与ospf的机制
网络·网络协议·学习·算法·智能路由器·信息与通信
我想学LINUX5 小时前
【2024年华为OD机试】 (C卷,100分)- 消消乐游戏(Java & JS & Python&C/C++)
java·c语言·javascript·c++·游戏·华为od
KeyPan6 小时前
【Ubuntu与Linux操作系统:九、Shell编程】
linux·运维·服务器·算法·ubuntu
ac-er88886 小时前
Go语言中http.Transport的Keep-Alive配置与性能优化方法
网络·网络协议·http·golang