服务端:
// Coroutine.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include<boost/asio/co_spawn.hpp>//包含启动协程的函数
#include<boost/asio/detached.hpp>//
#include<boost/asio/io_context.hpp>//协程调度需要执行器,这个包含一个执行器
#include<boost/asio/ip/tcp.hpp>
#include<boost/asio/signal_set.hpp>//优雅退出信号
#include<boost/asio/write.hpp>//写数据要用到发送头文件
#include <iostream>
using boost::asio::ip::tcp;
using boost::asio::awaitable;//可等待协程作用域
using boost::asio::co_spawn;//启动协程的关键字
using boost::asio::detached;
using boost::asio::use_awaitable;//使协程可以等待
namespace this_coro = boost::asio::this_coro;//返回当前协程所执行的环境
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);
co_await async_write(socket, boost::asio::buffer(data, n), use_awaitable);
//让协程等待这个异步函数完成
}
}
catch (std::exception& e) {
std::cout << "exception is" << e.what() << std::endl;
}
}
awaitable<void> listener() {//将这个函数设置为可等待,协程就可以直接调用这个函数了
auto executor = co_await this_coro::executor;
//通过co_await的方式获取协程的调度器,异步的找这个调度器,如果找不到就把它挂起
//把使用权交给主线程中其他协程,直到能够捕获再继续往下走
tcp::acceptor acceptor(executor, { tcp::v4(),10086 });//让接受操作在协程内部执行
for (;;) {//来一个连接就创建一个连接
tcp::socket socket = co_await acceptor.async_accept(use_awaitable);
//参数告诉asio把该异步函数变成协程能够使用的函数并通过co_await用协程的方让协程挂起去等待
// 没等到连接将资源归还主线程,可能去执行其他协程
// 等到连接后协程被唤醒,才继续往下走
co_spawn(executor, echo(std::move(socket)), detached);//在协程里面再启动一个协程,
}
}
int main()
{
try {
boost::asio::io_context io_context(1);
boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
//将信号绑定到上下文上,绑定的信号有ctralC,中断等
signals.async_wait([&](auto, auto) {
io_context.stop();
});//lambda表达式用来指示捕获信号后干什么,处理几个信号传几个参数
co_spawn(io_context, listener(), detached);//通过co_spawn启动一个协程
//(协程调度器,也就是该协程由谁调度;协程要执行的任务;该协程启动方式:分离主线程
//
//co_spawn(io_context, listener(), detached);先启动上面的协程,如果上面的被挂起就到这个协程
io_context.run();//iocontext没有绑定任何异步事件的时候run会直接返回
}
catch (std::exception& e) {
std::cout << "exception is" << e.what() << std::endl;
}
}
客户端
#include <iostream>
#include<boost/asio.hpp>
using namespace std;
using namespace boost::asio::ip;
const int MAX_LENGTH = 1024;
int main()
{
try {
boost::asio::io_context ioc;
tcp::endpoint remote_ep(address::from_string("127.0.0.1"), 10086);
tcp::socket sock(ioc);
boost::system::error_code error = boost::asio::error::host_not_found;
sock.connect(remote_ep, error);
if (error) {
cout << "connection failed,code is" << error.value() << "error msg is" << error.message() << std::endl;
return 0;
}
std::cout << "enter message";
char request[MAX_LENGTH];
std::cin.getline(request, MAX_LENGTH);
size_t request_length = strlen(request);
boost::asio::write(sock, boost::asio::buffer(request, request_length));
char reply[MAX_LENGTH];
size_t reply_length = boost::asio::read(sock, boost::asio::buffer(reply, request_length));
cout << "reply is" << string(reply, reply_length) << endl;
getchar();
}
catch (std::exception& e) {
std::cerr << "Exception is" << e.what() << std::endl;
}
}