Boost.Asio—使用协程进行网络编程

简介
本文基于 Boost.Asio 编写一个 TCP echo 程序. 且使用协程来处理异步逻辑.
Asio
下载:https://sourceforge.net/proje...
VS 中使用:项目 - 属性 - VC目录 - 包含目录,添加 YourPath\asio-1.18.2\include
官方文档:https://www.boost.org/doc/lib...
1. 头文件及全局变量

#include #include #include #include #include #include #include #include using asio::ip::tcp; static std::mutex coutLock; // 简单起见,此处回显固定的消息 static std::string Message("hello, asio!"); static size_t MsgLength = Message.size();

2. TcpServer
// 异步 class TcpServer { public: TcpServer(asio::io_context& context, uint16_t port) : m_context(context), m_acceptor(context, tcp::endpoint(tcp::v4(), port)) { waitForConnection(); }private: asio::awaitable waitForConnection() { while (true) { tcp::socket socket(m_context); co_await m_acceptor.async_accept(socket, asio::use_awaitable); coutLock.lock(); std::cout << "New Connection From: " << socket.remote_endpoint() << '\n'; coutLock.unlock(); // 创建协程,处理新到的连接 asio::co_spawn(socket.get_executor(), handleConnection(std::move(socket)), asio::detached); } }static asio::awaitable handleConnection(tcp::socket&& socket) { std::vector buffer(MsgLength); try { while (true) { std::size_t n = co_await asio::async_read(socket, asio::buffer(buffer), asio::use_awaitable); co_await asio::async_write(socket, asio::buffer(buffer, n), asio::use_awaitable); } } catch (const std::exception& e) { std::lock_guard lock(coutLock); std::cerr << "Handle Connection Error: " << e.what() << '\n'; } }private: asio::io_context& m_context; tcp::acceptor m_acceptor; };

此时不用再传入回调函数,而是将回调函数替换为 asio::use_awaitable,然后再 co_await async_xxx(...); 即可.
3. TcpClient
// 同步 class TcpClient { public: TcpClient(asio::io_context& context) : m_context(context), m_socket(context), m_buffer(MsgLength) {}void connect(const std::string& host, const std::string& service) { try { tcp::resolver resolver(m_context); auto endpoints(resolver.resolve(host, service)); asio::connect(m_socket, endpoints); } catch (const std::exception& e) { std::lock_guard lock(coutLock); std::cerr << "Connect Error: " << e.what() << '\n'; } }void echo(const std::string& msg) { size_t length = asio::write(m_socket, asio::buffer(msg.c_str(), msg.size())); length = asio::read(m_socket, asio::buffer(m_buffer, length)); coutLock.lock(); for (std::size_t i = 0; i < length; i++) { std::cout << m_buffer[i]; } std::cout << '\n'; coutLock.unlock(); m_socket.close(); }private: asio::io_context& m_context; tcp::socket m_socket; std::vector m_buffer; };

【Boost.Asio—使用协程进行网络编程】4. 主程序
static void clientThread(asio::io_context& context) { TcpClient client(context); client.connect("127.0.0.1", "6666"); client.echo(Message); }int main() { try { asio::io_context context; TcpServer server(context, 6666); std::thread t(clientThread, std::ref(context)); t.detach(); context.run(); } catch (const std::exception& e) { std::lock_guard lock(coutLock); std::cerr << "Main Error: " << e.what() << '\n'; } }

New Connection From: 127.0.0.1:55647 hello, asio! Read Error: End of file

    推荐阅读