asio::streambuf相对于原始数组的优势

4
我不太明白使用streambuf相比常规数组的好处。让我解释一下我的问题。我有一个通过Rijndael 128 ECB加上一些简单的密码来加密剩余数据的网络连接,这些包结构为整个包的长度+操作码+数据。我必须实际复制所有数据从流缓冲区中,以便我可以应用解密算法?为什么要复制我已经拥有的数据呢?
发送数据时也遇到同样的问题。当处于安全模式时,数据包结构为整个包的长度+crc+数据,其中crc和数据都被加密。我可以创建一个MakePacket(HEADER,FORMAT,...)的巨兽函数来分配数组、格式化数据包、添加crc并加密它,但我想避免变长函数。我不能使用结构体,因为数据包具有动态长度,因为它可能包含数组或字符串。如果我使用MakePacket(unsigned char opcode,&streambuf sb),那么crc又会有问题->必须复制才能加密。
我应该在发送时使用变长巨兽函数与常规数组作为缓冲区,同时使用unsigned char pbyRecvBuffer[BUFFERMAXLEN]进行接收吗?
我不太确定如何设计这种通信方式,以避免复制数据。
谢谢你的回答。
1个回答

3
使用streambuf时,可以通过使用操作迭代器的算法(如std::istreambuf_iteratorboost::asio::buffers_iterator)而不是将数据从streambuf复制到另一个数据结构中来最小化数据的复制。
对于流式应用程序协议,boost::asio::streambuf通常优于boost::asio::buffer()兼容类型,例如原始数组。例如,考虑HTTP,其中使用定界符来标识可变长度头和正文之间的边界。更高级别的read_until()操作提供了一种优雅的方式来读取协议,因为Boost.Asio将处理内存分配、检测定界符,并在消息边界被达到时调用完成处理程序。如果应用程序使用原始数组,则需要读取块并将每个碎片化块复制到聚合内存缓冲区中,直到找到适当的定界符为止。
如果应用程序能确定要读取的确切字节数,则考虑使用boost::array处理固定长度部分,使用std::vector处理可变长度部分。例如,具有以下内容的应用程序协议:
  • 固定长度的正文可以读入boost::array
  • 包含足够信息以确定后续可变长度正文长度的固定长度标头可以使用std::vector来读取固定大小标头,一旦确定了正文长度,就调整vector的大小,然后读取正文。
在问题的上下文中,如果length_of_whole_packet是固定长度的,则应用程序可以将其读入std::vector,根据确定的正文长度调整vector的大小,然后将剩余数据读入vector。解密算法可以直接在vector上操作,并使用输出迭代器(例如std::back_insert_iterator)以及辅助输出缓冲区(如果算法无法原地完成)。加密待写入的数据同样适用。

啊,是的,你说得对。我以前在一个HTTPS客户端项目中实际上使用了streambuf。所以我的问题实际上有点愚蠢 :)。好吧,在这个项目中,我放弃了streambuf,因为没有方便的方法来使用块密码作为Rijndael并在读取/准备发送数据后就地解密/加密。我选择了静态数组。足够大,能够处理从recv接收到的最大数据包,至于发送,我仍在考虑是否应该将其设置为动态分配的原始数组(问题是在分配空间之前计算数据包的大小)。 - Schnappi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接