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
推荐阅读
- 急于表达——往往欲速则不达
- 慢慢的美丽
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量
- 2019-02-13——今天谈梦想()
- 考研英语阅读终极解决方案——阅读理解如何巧拿高分
- Ⅴ爱阅读,亲子互动——打卡第178天
- 由浅入深理解AOP
- 低头思故乡——只是因为睡不着
- 【译】20个更有效地使用谷歌搜索的技巧
- 取名——兰