Boost asio的async_write函数

来源:互联网 发布:t2雷霆机甲数据 编辑:程序博客网 时间:2024/04/30 21:44

Boost asio是一个异步网络通信的库,其中async_write是一个比较常用的函数,但是,如果没有正确的使用,就可能会出现一些意想不到的潜在Bug。例如下面的代码:

for (int i=0; i < n; i++){    boost::asio::async_write(        socket_,        boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),        boost::asio::transfer_at_least(buffer[i].length_),        boost::bind(            &HttpServer::HandleTcpSend,            shared_from_this(),            boost::asio::placeholders::error,            boost::asio::placeholders::bytes_transferred                 )    );    // Do something} 


代码很简单,就是循环N次,发送N块buffer。我们的目标是,接收端依次接收buffer1,buffer2,……,buffer n。但是,事实上,上面的代码是有问题的,服务器可能会接收到完全错乱的数据。先看一下正确的写法,代码如下:

 int i=0;    boost::asio::async_write(        socket_,        boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),        boost::asio::transfer_at_least(buffer[i].length_),        boost::bind(             &HttpServer::HandleTcpSend,             shared_from_this(),            boost::asio::placeholders::error,            boost::asio::placeholders::bytes_transferred                 )    );     // Do something void HttpServer::HandleTcpSend(const boost::system::error_code& err,     size_t bytes_transferred){    i++;    boost::asio::async_write(        socket_,        boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),        boost::asio::transfer_at_least(buffer[i].length_),        boost::bind(             &HttpServer::HandleTcpSend,             shared_from_this(),            boost::asio::placeholders::error,            boost::asio::placeholders::bytes_transferred                 )    );}

问题。这个并不是asio的限制,底层套接字的一些函数,如发送等也无法保证一次异步操作就把所有的数据都通过TCP流发送出去。async_write将被告知有多少字节实际发送了,然后要求在下一次异步操作时发送剩余的字节。async_write是通过一次或者多次调用async_write_some函数来实现的,那么如果在第一个async_write还没有完成就调用第二个async_write,async_write_some就有可能先将第二个buffer的数据先发送出去。

因此,NEVER start your second async_write before the first has completed.


From http://www.sizeof.cn/html/2009/143.html

原创粉丝点击