http://www.boost.org/doc/libs/1_55_0b1/doc/html/boost_asio/reference/buffer.html
http://www.boost.org/doc/libs/1_59_0/doc/html/boost_asio/overview/core/buffers.html
https://www.cnblogs.com/my_life/articles/5953485.html
https://www.boost.org/doc/libs/1_59_0/doc/html/boost_asio/overview/core/buffers.html mutable_buffer, const_buffer, streambuf的由来和使用
The boost::asio::buffer
function is used to create a buffer object to represent raw memory, an array of POD elements, a vector of POD elements, or a std::string.
boost::asio::buffer是一个函数。
A buffer object represents a contiguous region of memory as a 2-tuple consisting of a pointer and size in bytes.
A tuple of the form {void*, size_t}
specifies a mutable (modifiable) region of memory. (一个可写区域,用mutable_buffer类来表示)
Similarly, a tuple of the form {const void*, size_t}
specifies a const (non-modifiable) region of memory. (一段只读区域,用const_buffer类来表示)
These two forms correspond to the classes mutable_buffer
and const_buffer
, respectively.
mutable_buffer和const_buffer属于通过buffer函数创建返回的buffer对象的两个内部类对象,一般不单独使用,详情见文末。
sock.send(boost::asio::buffer(data, size));
In the above example, the return value of boost::asio::buffer
meets the requirements of the ConstBufferSequence concept so that it may be directly passed to the socket's write function.
boost::asio::buffer()函数可以返回一个const 只读buffer,让别人来读。
A buffer created for modifiable memory also meets the requirements of the MutableBufferSequence concept.
boost::asio::buffer()函数也可以返回一个mutable 可写buffer,供别人来写。
ConstBufferSequence , MutableBufferSequence 只是一个概念(对应socket::send()的模版参数),对应的const_buffer和mutable_buffer才是boost::asio的类。
ip::tcp:socket的send()函数签名如下:
template<typename ConstBufferSequence>
std::size_t send(const ConstBufferSequence & buffers);
The mutable_buffer
class provides a safe representation of a buffer that can be modified. It does not own the underlying data, and so is cheap to copy or assign.
Accessing Buffer Contents
The contents of a buffer (单独一个buffer)may be accessed using the buffer_size
and buffer_cast
functions:
boost::asio::mutable_buffer b1 = ...; std::size_t s1 = boost::asio::buffer_size(b1); unsigned char* p1 = boost::asio::buffer_cast<unsigned char*>(b1); boost::asio::const_buffer b2 = ...; std::size_t s2 = boost::asio::buffer_size(b2); const void* p2 = boost::asio::buffer_cast<const void*>(b2);
For convenience, thebuffer_size
function also works on buffer sequences(buffer 序列,例如vector<const_buffer> buffers = ...; //这是一个buffer序列)
(that is, types meeting the ConstBufferSequence or MutableBufferSequence type requirements).
In this case, the function returns the total size of all buffers in the sequence.
Buffer Copying
The buffer_copy
function may be used to copy raw bytes between individual buffers and buffer sequences.
In particular, when used with the buffer_size
, the buffer_copy
function can be used to linearise a sequence of buffers. For example:
vector<const_buffer> buffers = ...; //这是一个buffer序列
vector<unsigned char> data(boost::asio::buffer_size(buffers)); //申请一个大小为buffer序列的长度的raw buffer
boost::asio::buffer_copy(boost::asio::buffer(data), buffers); //把buffer序列转换成一个single asio::buffer()
buffer_size, buffser_cast, buffer_copy既可以用在一个单独的buffer上,也可以操作整个buffer序列。
Buffer Invalidation
A buffer object does not have any ownership of the memory it refers to. It is the responsibility of the application to ensure the memory region remains valid until it is no longer required for an I/O operation.
When the memory is no longer available, the buffer is said to have been invalidated.
Buffers and Scatter-Gather I/O
To read or write using multiple buffers (i.e. scatter-gather I/O), multiple buffer objects may be assigned into a container that supports the MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts:
用多个buffer(即buffer序列)进行读写操作,简称scatter-gather I/O
char d1[128];
std::vector<char> d2(128);
boost::array<char, 128> d3;
boost::array<mutable_buffer, 3> bufs1 = {
boost::asio::buffer(d1),
boost::asio::buffer(d2),
boost::asio::buffer(d3) };
bytes_transferred = sock.receive(bufs1);
std::vector<const_buffer> bufs2;
bufs2.push_back(boost::asio::buffer(d1));
bufs2.push_back(boost::asio::buffer(d2));
bufs2.push_back(boost::asio::buffer(d3));
bytes_transferred = sock.send(bufs2);
http://mmoaay.gitbooks.io/boost-asio-cpp-network-programming-chinese/content/Chapter6.html
Boost.Asio在处理I/O操作时支持两种类型的buffer:
- boost::asio::buffer():这种buffer关联着一个Boost.Asio的操作(我们使用的buffer被传递给一个Boost.Asio的操作)
- boost::asio::streambuf:这个buffer继承自std::streambuf,在网络编程中可以和STL stream一起使用
size_t read_complete(boost::system::error_code, size_t bytes){ ... }
char buff[1024];
read(sock, buffer(buff), read_complete);
write(sock, buffer("echo\n"));
通常来说使用这个就能满足你的需要,如果你想要更复杂,你可以使用streambuf来实现。
这个就是你可以用streambuf对象做的最简单也是最坏的事情:
streambuf buf;
read(sock, buf);
这个会一直读到streambuf对象满了,然后因为streambuf对象可以通过自己重新开辟空间从而获取更多的空间,它基本会读到连接被关闭。
你可以使用read_until一直读到一个特定的字符串:
streambuf buf;
read_until(sock, buf, "\n");
这个例子会一直读到一个“\n”为止,把它添加到buffer的末尾,然后退出read方法。
streambuf buf;
std::ostream out(&buf);
out << "echo" << std::endl;
write(sock, buf);
这是非常直观的;你在构造函数中传递你的streambuf对象来构建一个STL stream,将其写入到你想要发送的消息中,然后使用write来发送buffer的内容。
使用下面的代码片段把streambuf的内容输出到console中
streambuf buf;
...
std::cout << &buf << std::endl; //把所有内容输出到console中
std::string to_string(streambuf &buf) {
std::ostringstream out;
out << &buf;
return out.str();
}
协程---高级主题
Boost.Asio的作者在2009-2010年间实现了非常酷的一个部分,协程(Co-routines),它能让你更简单地设计你的异步应用。
正常的流程已经在情形1种展示了,如果使用协程,你会尽可能的接近情形2。简单来说,就是协程允许在方法中的指定位置开辟一个入口来暂停和恢复运行。
class talk_to_svr : public boost::enable_shared_from_this<talk_to_svr>, public coroutine, boost::noncopyable { ... void step(const error_code & err = error_code(), size_t bytes = 0) { reenter(this) { for (;;) { yield async_write(sock_, write_buffer_, MEM_FN2(step,_1,_2) ); yield async_read_until( sock_, read_buffer_,"\n", MEM_FN2(step,_1,_2)); yield service.post( MEM_FN(on_answer_from_server)); } } } };
先改变的事就是:我们只有一个叫做step()的方法,而没有大量类似connect(),on_connect(),on_read(),do_read(),on_write(),do_write()等等的成员方法。
http://www.cnblogs.com/my_life/articles/9075758.html 协程的步步解析深入
Bytewise Traversal of Buffer Sequences
The buffers_iterator<>
class template allows buffer sequences (i.e. types meeting MutableBufferSequence
or ConstBufferSequence
requirements) to be traversed as though they were a contiguous sequence of bytes.
Helper functions called buffers_begin() and buffers_end() are also provided, where the buffers_iterator<> template parameter is automatically deduced.
As an example, to read a single line from a socket and into a std::string
, you may write:
boost::asio::streambuf sb;
...
std::size_t n = boost::asio::read_until(sock, sb, '\n');
boost::asio::streambuf::const_buffers_type bufs = sb.data();
std::string line(
boost::asio::buffers_begin(bufs),
boost::asio::buffers_begin(bufs) + n);
==========================================================================
https://segmentfault.com/a/1190000003706906
buffer
库中提供了mutable_buffer
和const_buffer
两种单个缓冲,以及 mutable_buffers_1
和const_buffers_1
两种缓冲序列,asio提供了一些操作:
-
buffer_cast<char*>(mb)
:单个缓冲转成指针 -
buffer_size(buf)
:取得缓冲区大小 -
buffer_copy(bufs, bufd)
:缓冲区(包括单个和序列)之间复制尽可能多的元素,它是安全的,不会出现溢出的情况
//`buffer` can wrap nearly everything
vector<char> underlying_buffer(50);
auto buf1 = buffer(underlying_buffer); //通过buffer函数返回一个buffer对象,buffer对象内部会员const_buffer和mutable_buffer两个内部类对象
char underlying_string[] = "Hello";
auto buf2 = buffer(underlying_string);
buffer_copy(buf2, buf1); // returns 6
std::string s(buffer_begin(buf1), buffer_end(buf1));
========
The mutable_buffer
class provides a safe representation of a buffer that can be modified. It does not own the underlying data, and so is cheap to copy or assign.
The const_buffer
class provides a safe representation of a buffer that cannot be modified. It does not own the underlying data, and so is cheap to copy or assign.
Accessing Buffer Contents
The contents of a buffer may be accessed using the buffer_size
and buffer_cast
functions:
boost::asio::mutable_buffer b1 = ...;
std::size_t s1 = boost::asio::buffer_size(b1);
unsigned char* p1 = boost::asio::buffer_cast<unsigned char*>(b1);
The boost::asio::buffer_cast
function permits violations of type safety, so uses of it in application code should be carefully considered.
Requirements
Header: boost/asio/buffer.hpp
streambuf
streambuf
是Asio能灵活地异步调控数据的关键。它能自动增长和回收consumed space。在使用的时候有这些要点:
-
streambuf
分为input sequence和output sequence两部分,这都是继承自std::streambuf
的理念。 -
用
data()
来获取输入序列(常缓冲),prepare(n)
来获取输出序列(变缓冲)。 -
用
commit(n)
来将从输出序列提交到输入缓冲,用consume(n)
来将输入缓冲中的数据丢弃,代表已经处理完毕。 -
read数据的过程:先
prepare
好固定大小的缓冲区,然后buffer_copy
进去一些数据,拷贝了多少数据就commit
多少数据。然后再从prepare
开始,拷贝到手头上的数据没有了为止。 -
streambuf
不可拷贝,所以乖乖传引用或者指针吧。
这里有一些文档没有说明但是需要了解的细节:
-
自动增长的功能是通过
reserve(n)
函数管理的,这个函数在overflow
和prepare
处会调用,用于保证输出缓冲区里有至少n字节的空间。 -
缓冲区的大小是没有限制的,
max_size
一般是size_t
能表示的最大数字,相当于内存的极限。 -
std::istream(sb).ignore(n)
,sb.gbump(n)
,sb.consume(n)
有相同的效果,但是ignore
和consume
有防下溢机制。
https://www.cnblogs.com/my_life/articles/4892557.html
============================
https://www.cnblogs.com/my_life/articles/5953485.html