C++ Asio:是否有自动调整大小的缓冲区用于接收输入?

C++ Asio:是否有自动调整大小的缓冲区用于接收输入?,c++,boost,boost-asio,C++,Boost,Boost Asio,Asio:是否有自动调整大小的缓冲区用于接收输入 我事先不知道要收到的数量,所以我会在邮件头中发送这个数量 我已经看了一个使用页眉的示例,但是这个示例假设了最大主体尺寸的规范 看看asio::buffer类,我必须提供一些底层缓冲区,因此不灵活。相反,我关注的是asio::streambuf类,但如下所示使用它会导致分段/内存错误 我尝试为只读头\u LEN字节(即头)指定最大大小 这种方法错了吗 void do_recv_header() { asio::streambuf buf(

Asio:是否有自动调整大小的缓冲区用于接收输入

我事先不知道要收到的数量,所以我会在邮件头中发送这个数量

我已经看了一个使用页眉的示例,但是这个示例假设了最大主体尺寸的规范

看看asio::buffer类,我必须提供一些底层缓冲区,因此不灵活。相反,我关注的是asio::streambuf类,但如下所示使用它会导致分段/内存错误

我尝试为只读
头\u LEN
字节(即头)指定最大大小

这种方法错了吗

void do_recv_header() 
{
    asio::streambuf buf(HEADER_LEN);
    asio::async_read(*g_selected_conn, buf, [this, &buf](const system::error_code& ec, std::size_t bytes_transferred)
    {
        if (ec != 0) {
            std::cout << "async_read() error: " << ec.message() << " (" << ec.value() << ") " << std::endl;
            remove_closed_conn(g_selected_conn);
            SetEvent(g_wait_event);
        }
        else {
            std::istream is(&buf);
            int body_len;
            is >> body_len;
            std::cout << body_len << std::endl;
            do_recv_body(body_len);
        }
    });
}
void do_recv_头()
{
asio::streambuf buf(收割台长度);
asio::异步读取(*g_已选择连接,buf,[this,&buf](常量系统::错误代码&ec,std::大小\u t字节\u传输)
{
如果(ec!=0){
std::cout是一个自动调整大小的缓冲区类。在启动读取操作时,通常使用这种缓冲区类型,读取操作的完成取决于数据的内容,而不一定取决于数据的大小。例如,可以使用读取直到换行,而不知道或指定可以读取的数据量

在具有固定长度的头的应用程序的情况下,包含主体的长度,并且头部后面跟着一个可变长度的主体,考虑使用缓冲类型,例如<代码> STD::vector < /代码>。这将提供与<代码> Boo::ASIO::StudiBuf >相同的灵活性,同时简化了一些BooKey。平:

std::向量缓冲区;
//读标题。
调整缓冲区大小(协议::头大小);
boost::asio::read(套接字,boost::asio::buffer(buffer));
//从标题提取正文大小,调整缓冲区大小,然后读取
//身体。
auto body_size=parse_头(缓冲区);
调整缓冲区大小(主体大小);
boost::asio::read(套接字,boost::asio::buffer(buffer));
处理单元体(缓冲器);
调整
向量的大小
并不表示在读取操作中将读取多少数据。使用
streambuf
时,必须通过这些操作直接管理输入和输出序列:

boost::asio::streambuf streambuf;
//将标题读入streambuf的输出序列。
自动字节传输=boost::asio::read(套接字、,
streambuf.prepare(协议::头大小);
//将从输出序列读取的数据提交到输入序列
//顺序。
streambuf.commit(传输的字节);
//从标题中提取正文大小。这可能
//使用streambuf的所有输入序列。
auto body_size=解析_头(streambuf);
//清除输入序列。
streambuf.consume(streambuf.size());
//将Ready body转换为streambuf的输出序列。
传输的字节数=boost::asio::read(套接字、,
准备(车身尺寸);
//将从输出序列读取的数据提交到输入序列
//顺序。
streambuf.commit(传输的字节);
//将所有流提取到体内。
流程主体(streambuf);

以下是此方法的完整示例:

#包含//标准::数组
#include//std::bind
#包括//std::cout,std::endl
#include//std::vector
#包括
//本例对处理程序不感兴趣,因此提供一个noop函数
//将传递给bind以满足处理程序概念要求。
void noop(){}
//应用程序协议将由一个固定大小的报头组成
//包含std::size\t,长度如下
//可变长度主体。为了保持简单,请提供一些细节
//如endian处理。
名称空间协议{
枚举
{
标题大小=大小(标准::大小)
};
}//名称空间协议
std::vector build_头(const std::string和body)
{
std::向量缓冲区(协议::头大小);
汽车车身尺寸=车身尺寸();
std::memcpy(&buffer[0],&body\u size,sizeof body\u size);
返回缓冲区;
}
std::size\u t parse\u头(const std::vector&buffer)
{
return*reinterpret_cast(&buffer[0]);
}
int main()
{
使用boost::asio::ip::tcp;
//创建所有I/O对象。
boost::asio::io_服务io_服务;
tcp::acceptor acceptor(io_服务,tcp::endpoint(tcp::v4(),0));
tcp::socket socket1(io_服务);
tcp::socket socket2(io_服务);
//连接插座。
acceptor.async_accept(socket1,std::bind(&noop));
socket2.async_connect(acceptor.local_endpoint(),std::bind(&noop));
io_service.run();
io_service.reset();
//将消息从socket1写入socket2。
std::string test_message=“这是一条测试消息”;
{
自动标头=生成标头(测试消息);
//将标题和正文收集到单个缓冲区中。
std::数组缓冲区={{
boost::asio::buffer(标头),
boost::asio::buffer(测试消息)
}};
//将标题和正文写入套接字。
boost::asio::write(socket1,缓冲区);
}
//阅读socket2。
{
//使用向量以允许基于
//需要读取的数据量。这也减少了
//如果向量被重用,重新分配的数量。
向量缓冲区;
//读标题。
调整缓冲区大小(协议::头大小);
boost::asio::read(socket2,boost::asio::buffer(buffer));
//从标题提取正文大小,调整缓冲区大小,然后读取
//身体。
auto body_size=parse_头(缓冲区);
调整缓冲区大小(主体大小);
boost::asio::read(socket2,boost::asio::buffer(buffer));
//确认已读取正文。
断言(标准::相等(开始(缓冲区),结束(缓冲区),
开始(测试消息));

std::你知道它在哪一行出错吗?抱歉,不知道,但它与streambuf有关。首先,如果你已经知道要填充多少个八位字节/字节,为什么不使用固定大小的常规缓冲区?其次,我认为使用
boost::asio::async_read_直到
boost::asio::async_read_some
使mor我使用了一个固定大小的缓冲区,因为我希望async_read仅在读取时停止