我最近问了一个关于 Boost Asio 的问题,并从其中一位成员那里得到了一个有趣的建议 https://coliru.stacked-crooked.com/a/6e17518e3a3850f7.
它使用
async_read_until
并读取直到出现 '
',如果您正在读取未格式化的数据,这可以正常工作,但这不是最好的选择。
我了解到应该使用
async_read_some()
,所以在网上搜索后,看到一些示例代码,我尝试使用async_read_some()
重现相同的结果。
下面是我的示例代码,但不幸的是我的尝试失败了,
#include <boost/asio.hpp>
#include <iostream>
namespace asio = boost::asio;
namespace this_coro = asio::this_coro;
using asio::ip::tcp;
template <typename T> using Defer = asio::deferred_t::as_default_on_t<T>;
using Socket = Defer<tcp::socket>;
using Acceptor = Defer<tcp::acceptor>;
void handler(
const boost::system::error_code& error, // Result of operation.
std::size_t bytes_transferred // Number of bytes read.
)
{
std::cout << bytes_transferred << std::endl;
return;
}
asio::awaitable<void> session(Socket socket)
{
auto ep = socket.remote_endpoint();
std::cout << "New session for " << ep << "\n";
size_t requests_handled = 0;
for (std::string buf;; ++requests_handled)
{
char data[32] = { 0 };
socket.async_read_some(boost::asio::buffer(data, sizeof(data)), handler);
}
std::cout << " -- Session " << ep << " handled " << requests_handled << " requests" << std::endl;
}
asio::awaitable<void> listener(uint16_t port)
{
auto ex = co_await this_coro::executor;
Acceptor acc(ex, { {}, port });
for (;;)
{
co_spawn(ex, session(co_await acc.async_accept()), asio::detached);
}
}
int main()
{
asio::io_context ioc(1);
co_spawn(ioc, listener(8989), asio::detached);
ioc.run(); // single threaded, everything on main thread
}
除了我如何破坏工作示例之外,我还想知道如何读取整个传入数据,传入数据的大小各不相同,通过 tcp 套接字读取所有传入数据的最佳方法是什么?
我是 Boost Asio 和 C++ 的新手,我尽力自己找到解决方案,但不幸的是没有成功获得与
async_read_until
相同的结果并读取所有不同大小的传入 tcp 数据包。
谢谢
为什么要尝试以回调方式处理读取的输出?当你已经有一个协程时,这是没有意义的。只需使用已经是默认完成标记的
asio::deferred
:
co_await socket.async_read_some(boost::asio::buffer(data, sizeof(data)));
这样,由于现在保证完成是协程的恢复,因此数组的生命周期不是问题,因为协程拥有堆栈帧。