zoukankan      html  css  js  c++  java
  • 发送接收缓存asio::buffer及asio::streambuf

    转自: https://www.jianshu.com/p/c33e7265acd8

    什么是asio::buffer

    数据的发送与接收,均是以字节流形式进行处理的,这就需要一个内存连续的存储区域供读取、写入,其表现形式就是内存指针和内存大小,asio::buffer就是用来表示这个存储区域的,根据功能不同,又分为可变mutable、不可变const,其定义如下:

    typedef std::pair<void*,std::size_t>  mutable_buffer;
    typedef std::pair<void*,std::size_t>  const_buffer;
    

    个人的理解:asio::buffer本身并不持有数据内容,我们可以理解为是一个适配器,用来提供给发送/接受动作来进行数据操作,这就是为什么在异步操作时要保证数据一直有效。

    构造asio::buffer

    asio::buffer的目标是创建缓存对象来表示原始存储区域,其构造可以接受如下内容:

    • 原始内存指针及其大小
    • POD类型的数组(std::array或者std::vector)
    • std::string

    需要注意的是,一旦构造完成,其大小就已经确定了,不会进行自动增长。

    asio::buffer的操作

    • 获取大小:boost::asio::buffer_size(buffer)
    • 获取内存指针:boost::asio::buffer_cast<T>(buffer)
    • 复制:boost::asio::buffer_copy
    • 运算:boost::asio::buffer(buffer+offset,size)

    asio::buffer序列

    Boost.Asio提供了asio::buffer序列,来支持scatter-gatter操作,即:

    • 接收数据到多个asio::buffer
    • 一次发送多个asio::buffer

    在使用序列时,会使用boost::asio::buffers_beginboost::asio::buffers_end进行遍历,从而进行操作,序列的迭代器类型为boost::asio::const_buffer或者boost::asio::mutable_buffer

    扩展asio::buffer

    asio::buffer本身比较简单,对其进行扩展以支持自己的buffer只能借助于序列,根据之前的理解,扩展实现的类只需要包含序列要求的内容即可,譬如一个const_buffer要实现的如下:

      typedef boost::asio::const_buffer value_type;  //缓存类型
      typedef const boost::asio::const_buffer* const_iterator; //缓存迭代器类型
      const boost::asio::const_buffer* begin() const {  ...; } //起始
      const boost::asio::const_buffer* end() const {  ...; }  //结束
    

    什么是asio::streambuf

    asio::streambuf是一个流缓存区,其本身包含了数据内容,这是与asio_buffer关键的区别点,asio::streambuf继承自标准库的streambuf,也就说asio::streambuf可以作为流缓冲区应用于符合标准库流定义的任何流。

    asio::buffer一旦创建大小就确定了,在进行读取操作时是不能自动增长的,而asio::streambuf是支持自动增长的,需要注意的是,自动增长也有最大大小限制,在构造asio::streambuf时可以设置其最大大小。

    提供的一些方法:

    • commit:将字符从输出序列移动到输入序列
    • consume:从输入序列中移除字符
    • data:获取输入序列的缓存列表
    • size:获取输入序列的大小
    • prepare:根据指定大小获取输出序列的缓存列表

    如何使用asio::streambuf

    本身可以作为数据输入/输出传递给对应发送/接收接口:

    • 作为数据输入进行发送
      使用data获取输入序列,当发送完成后调用consume移除已经发送的内容
    • 作为数据输出进行接收
      使用prepare获取输出序列,当读取完成后调用commit
    • 字节遍历
      使用buffers_beginbuffers_end来遍历序列获取字节流内容

    asio::streambuf使用示例

    写入示例:

    boost::asio::streambuf b;
    std::ostream os(&b);
    os << "Hello, World!
    ";
    // try sending some data in input sequence
    size_t n = sock.send(b.data());
    
    b.consume(n); // sent data is removed from input sequence
    

    读取示例:

    boost::asio::streambuf b;// reserve 512 bytes in output sequence
    boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512);
    
    size_t n = sock.receive(bufs);
    
    // received data is "committed" from output sequence to input sequence
    b.commit(n);
    std::istream is(&b);
    std::string s;
    is >> s;
    

    字节遍历示例:

    boost::asio::streambuf sb;
    ...
    std::size_t n = boost::asio::read_until(sock, sb, '
    ');
    
    boost::asio::streambuf::const_buffers_type bufs = sb.data();
    std::string line( boost::asio::buffers_begin(bufs), boost::asio::buffers_begin(bufs) + n);
    

    总结

    • 只要是采用异步操作,数据缓存都要在异步操作完成前保证有效性
    • buffer只是一个适配器,使用时注意原始数据源
    • streambuf包含数据内容,而且内存可以自动增长


    作者:长不胖的Garfield
    链接:https://www.jianshu.com/p/c33e7265acd8
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    升级windows 11小工具
    windows 10更新升级方法
    您需要了解的有关 Oracle 数据库修补的所有信息
    Step by Step Apply Rolling PSU Patch In Oracle Database 12c RAC Environment
    Upgrade Oracle Database Manually from 12.2.0.1 to 19c
    如何应用版本更新 12.2.0.1.210420(补丁 32507738 – 2021 年 4 月 RU)
    xtrabackup 安装、备份和恢复
    Centos_Lvm expand capacity without restarting CentOS
    Centos_Lvm_Create pv vg lv and mount
    通过全备+relaylog同步恢复被drop的库或表
  • 原文地址:https://www.cnblogs.com/xiaouisme/p/13452866.html
Copyright © 2011-2022 走看看