定义
面向流的I/O对象
在Boost.Asio
中,socket等I/O对象是面向流的,意味着:
- 没有消息边界,被传输的数据是一段连续的字节流
- 读取/写入操作传输的可能比请求的要少,被称为
a short read
/a short write
面向流的I/O对象根据同步/异步、读取/写入可以分为四种:
- 同步读取流
读取接口为read_some()
- 异步读取流
读取接口为async_read_some()
- 同步写入流
写入接口为write_some()
- 异步写入流
写入接口为async_write_some()
由于传输的可能比请求的要少,譬如需要发送1MB,实际上一次只写入了1KB,那么想要完成传输,就需要继续写入直到全部发送完成。在Boost.Asio
中提供的read
、async_read
、write
、async_write
等接口已经封装好了这些操作。
数据缓存
读取需要从数据缓存获取内容,写入需要向数据缓存写入内容,在Boost.Asio
中提供了boost.asio.buffer
和boost.asio.streambuf
作为数据缓存,两者不同之处在于boost.asio.buffer
只是真实存储空间的适配器,而boost.asio.streambuf
包含有存储空间。
完成条件
流对象是没有消息边界的,也就是说,只要不主动/被迫停止读取,可以一直读到流真正结束,例如在执行读取时,会一直读取到流EOF,或者流关闭出现异常。在实际使用中,通常会有对应的条件表示本次读取/写入可以结束了,即为完成条件。
Boost.Asio
提供了两种完成方式:
-
xxx_until
用来读取/写入到满足until
条件即可返回 - 完成条件
CompletionCondition
自定义的函数,预设有transfer_all
、transfer_exactly
、transfer_at_least
错误码或者异常
Boost.Asio
提供了两种方式来表示出错:错误码;异常。
通常可以在执行函数传入boost::system::error_code
来获取错误码,来判断错误的发生;
如果没有获取错误码,则执行函数会抛出异常boost::system::system_error
。
发送/接收函数组一览
类型 | 同步发送 | 异步发送 | 同步接收 | 异步接收 |
---|---|---|---|---|
xxx | write | async_write | read | async_read |
xxx_at | write_at | async_write_at | read_at | async_read_at |
xxx_until | - | - | read_until | async_read_until |
函数原型
xxx
参数列表
- 面向流的I/O对象
- 数据缓存
- 完成条件[可选]
- 错误码[可选]
xxx_at
参数列表
- 面向流的I/O对象
- 指定偏移
- 数据缓存
- 完成条件[可选]
- 错误码[可选])
xxx_until
参数列表
- 面向流的I/O对象
- 数据缓存
- 字符/字符串/正则表达式/匹配条件
- 读取handler
读取handler的原型为:
read_handler(const boost::system::error_code&,std::size_t)
需要注意的是xxx_until
完成时接收到的数据包含了分割符,并没有将其丢弃,譬如以\n
作为终止条件,对于以下数据:
{ 'a','b',...,'c','\n','d','e',... }
数据缓存中的信息为:
{ 'a','b',...,'c','\n' }
其它
为何EOF
是错误
当流到了终点EOF
时,接受/发送操作会得到错误码boost::asio::error::eof
,因为一下原因:
- 读取到流终点与发送/接收函数的约定不同
譬如要读取N个字节,结果提前读到了流终点 - 可以用来与成功读取到0进行区分
如果发送缓存内容大小为0
此时发送操作会立即返回,读取到的长度也会是0。
网友评论