首页 > 代码库 > Boost.Asio c++ 网络编程翻译(10)
Boost.Asio c++ 网络编程翻译(10)
read/write方法
这些方法对一个流进行读写操作(可以是套接字,或者其他表现的像流的类):
async_read(stream, buffer [, completion],handler):这个方法异步地从一个流读取。结束时,处理方法被调用。处理方法的格式是:void handler(const boost::system::error_ code & err, size_tbytes);。你可以选择指定一个完成处理方法。完成处理方法会在每个read操作调用成功之后调用,然后告诉Boost.Asio async_read操作是否完成(如果没有完成,它会继续读取)。它的格式是:size_t completion(const boost::system::error_code& err, size_tbytes_transfered) 。当这个完成处理方法返回0时,我们认为read操作完成;如果它返回一个非0值,它表示了下一个async_read_some操作需要从流中读取的字节数。
接下来会有一个例子来详细展示这些。
async_write(stream, buffer [, completion],handler):这个方法异步地向一个流写入数据。参数的意义和async_read是一样的。
read(stream, buffer [, completion]):这个方法同步地从一个流中读取数据。参数的意义和async_read是一样的。
rite(stream, buffer [, completion]): 这个方法同步地向一个流写入数据。参数的意义和async_read是一样的。
° async_read(stream,stream_buffer [, completion], handler)
° async_write(strean,stream_buffer [, completion], handler)
° write(stream, stream_buffer[, completion])
° read(stream, stream_buffer[, completion])
首先,要注意第一个参数变成了流,而不单是socket。这个包含了socket但不仅仅是socket。比如,你可以用一个Windows的文件句柄来替代socket。
当下面情况出现时,所有read和write操作都会结束:
可用的缓冲区满了(当读取时)或者所有的缓冲区已经被写入(当写入时)。
完成处理方法返回0(如果你提供了这么一个方法)
错误发生时
下面的代码会异步地从一个socket中间读取数据直到读取到’\n’:
io_service service;
ip::tcp::socket sock(service);
char buff[512];
size_t up_to_en
int offset = 0;
stem::error_code &, size_t bytes) {
ter(const boost::s
y
for( size_t i = 0; i < bytes; ++i)
if ( buff[i + offset] == ‘\n‘)
return 0;
return 1;
}
void on_read(const boost::system::error_code &, size_t) {}
...
c_read(sock, buffer(buff), up_to_enter,on_read);
asy
n
Boost.Asio也提供了一些简单的完成处理仿函数:
? transfer_at_least(n)
? transfer_exactly(n)
? transfer_all(
)
例子如下:
char buff[512];
void on_read(constboost::system::error_code &, size_t) {}
// 读取32个字节
async_read(sock, buffer(buff),transfer_exactly(32), on_read);
上述的4个方法,不使用普通的缓冲区,而使用由Boost.Asio的std::streambuf类继承来的stream_buffer方法,stl流和流缓冲区非常复杂;下面是例子:
io_service service;
void on_read(streambuf& buf, constboost::system::error_code &,
size_t) {
std::istream in(&buf);
std::string line;
std::getline(in, line);
std::cout << "first line: "<< line << std::endl;
}
int main(int argc, char* argv[]) {
HANDLE file =::CreateFile("readme.txt", GENERIC_READ, 0, 0,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
0);
windows::stream_handle h(service, file);
streambuf buf;
uf, transfer_exactly(256),
async_read(h,
b
boost::bind(on_read,boost::ref(buf),_1,_2));
service.run();
}
在这里,我向你们展示了在一个Windows文件句柄上调用async_read。我们读取了前面的256个字符,然后把它们保存到缓冲区,当操作结束时。on_read被调用,然后创建std::istream来传递缓冲区,读取第一行(std::getline),最后把它输出到命令行中。
read_until/async_read_until方法
这些方法在条件满足之前一直读取:
async_read_until(stream, stream_buffer,delim, handler):这个方法启动一个异步read操作。read操作会在读取到某个分隔符时结束。分隔符可以是字符,std::string或者boost::regex。处理方法的格式为:void handler(const boost::system::error_code & err, size_tbytes);。
async_read_until(strem, stream_buffer,completion, handler):这个方法和之前的方法是一样的,但是没有分隔符,而是一个完成处理方法。完成处理方法的格式为:pair<iterator,bool> completion(iterator begin, iterator end);,其中迭代器的类型为buffers_iterator<streambuf::const_buffers_type>。你需要记住的是迭代器的类型是随机访问的迭代器。你扫描整个区间(begin,end),然后觉得read操作是否应该结束。你会返回一个结果对,第一个成员是一个指向最后被这个方法访问的字符的迭代器;第二个成员当read操作需要结束时返回true,否则返回false。
read_until(stream, stream_buffer, delim):这个方法执行一个同步的read操作,参数的意义和async_read_until一样。
read_until(stream, stream_buffer,completion):这个方法执行一个同步的read操作,参数的意义和async_read_until一样。
下面这个例子会一直读取直到读到一个指定的标点符号
typedefbuffers_iterator<streambuf::const_buffers_type> iterator;
std::pair<iterator, bool>match_punct(iterator begin, iterator end) {
while ( begin != end)
if ( std::ispunct(*begin))
return std::make_pair(begin,true);
return std::make_pair(end,false);
}
void on_read(constboost::system::error_code &, size_t) {}
...
streambuf buf;
async_read_until(sock, buf, match_punct,on_read);
如果我们想读到一个空格结束,我们需要把最后一行修改为:
async_read_until(sock, buff, ‘ ‘, on_read);
Boost.Asio c++ 网络编程翻译(10)