1. asio::buffer常用的构造方法
asio::buffer有多种的构造方法,而且buffer大小是自动管理的1.1 字符数组
- char d1[128];
- size_t bytes_transferred = socket.receive(boost::asio::buffer(d1));
1.2 字符向量
- std::vector<char> d2(128);
- size_t bytes_transferred = socket.receive(boost::asio::buffer(d2));
1.3 boost的数组
- boost::array<char, 128> d3;
- size_t bytes_transferred = sock.receive(boost::asio::buffer(d3));
1.4 字符串
- string str = "hello world";
- bytes_transferred = socket.send(boost::asio::buffer(str));
2. asio::buffer的常用方法
2.1 转换方法
- boost::asio::mutable_buffer b1 =boost::asio::buffer(str);
- unsigned char* p1 = boost::asio::buffer_cast<unsigned char*>(b1);
2.2 获取大小
- std::size_t s1 = boost::asio::buffer_size(b1);
3. asio::buffer的读写问题
注意 的是boost::asio::const_buffer是只读的buffer, 而boost::asio::mutable_buffer则可写。读写buffer也是有讲究的
3.1 与transfer_all()结合
- boost::array<char, 128> buf;
- boost::system::error_code ec;
- std::size_t n = boost::asio::read(
- socket,
- boost::asio::buffer(buf),
- boost::asio::transfer_all(),
- ec);
- if (ec)
- {
- // An error occurred.
- }
- else
- {
- // n == 128
- }
3.2 与transfer_at_least()结合
- std::size_t n = boost::asio::read(
- socket,
- boost::asio::buffer(buf),
- boost::asio::transfer_at_least(64),
- ec);
当然还有最常用的bytes_transferred,这个例子就很多了。
streambuf
asio::streambuf则是提供了一个流类型的buffer,它自身是能申请内存的。它的好处是可以通过stl的stream相关函数实现缓冲区操作,处理起来更加方便。
//通过streambuf发送数据
asio::streambuf b;
std::ostream os(&b);
os << "Hello, World!\n";
size_t n = sock.send(b.data()); // try sending some data in input sequence
b.consume(n); // sent data is removed from input sequence
//通过streambuf读数据
asio::streambuf b;
asio::streambuf::mutable_buffers_type bufs = b.prepare(512); // reserve 512 bytes in output sequence
size_t n = sock.receive(bufs);
b.commit(n); // received data is "committed" from output sequence to input sequence
std::istream is(&b);
std::string s;
is >> s;
另外,asio名字空间下还提供了一个的read_until函数,可以实现读到满足指定条件的字符串为止,对于解析协议来说非常有用。
size_t n = asio::read_until(sock, stream, '\n');
asio::streambuf::const_buffers_type bufs = sb.data();
std::string line(asio::buffers_begin(bufs), asio::buffers_begin(bufs) + n);
这个指定条件除了是字符串外,还可以是正则表达式,非常给力。这也是asio库为什么要依赖于boost.regex的原因。(虽然regex已经标准化了,但仍得使用boost.regex库。等什么时候asio也标准化后估计就可以直接使用std.regex库了)
自定义内存分配
异步IO操作时往往会申请动态内存,使用完后就释放掉;在IO密集型的场景中,频繁的申请释放内存对性能会有较大影响。为了避免这个问题,asio提供了一个内存池式的模型 asio_handler_allocate 和 asio_handler_deallocate 来复用内存。
例子我就不写了,可以参看boost官方文档示例,或者网上的这篇文章。
就我个人而言,并不赞成在项目的前期就使用上这个allocator,毕竟这样带来了很大的代码复杂度。而是作为一个性能优化点,在后期性能优化的时候再试试用它有没有效果。并且内存池的也有很多不同的方案,google的google-perftools也值得一试。