async_write async_write_some


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

[cpp]  view plain copy
 
  1. for (int i=0; i < n; i++)  
  2. {  
  3.     boost::asio::async_write(  
  4.         socket_,  
  5.         boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),  
  6.         boost::asio::transfer_at_least(buffer[i].length_),  
  7.         boost::bind(  
  8.             &HttpServer::HandleTcpSend,  
  9.             shared_from_this(),  
  10.             boost::asio::placeholders::error,  
  11.             boost::asio::placeholders::bytes_transferred           
  12.         )  
  13.     );  
  14.     // Do something  
  15. }   


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

 

[cpp]  view plain copy
 
  1.  int i=0;  
  2.     boost::asio::async_write(  
  3.         socket_,  
  4.         boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),  
  5.         boost::asio::transfer_at_least(buffer[i].length_),  
  6.         boost::bind(   
  7.             &HttpServer::HandleTcpSend,   
  8.             shared_from_this(),  
  9.             boost::asio::placeholders::error,  
  10.             boost::asio::placeholders::bytes_transferred           
  11.         )  
  12.     );  
  13.    
  14.     // Do something  
  15.    
  16. void HttpServer::HandleTcpSend(const boost::system::error_code& err,   
  17.     size_t bytes_transferred)  
  18. {  
  19.     i++;  
  20.     boost::asio::async_write(  
  21.         socket_,  
  22.         boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),  
  23.         boost::asio::transfer_at_least(buffer[i].length_),  
  24.         boost::bind(   
  25.             &HttpServer::HandleTcpSend,   
  26.             shared_from_this(),  
  27.             boost::asio::placeholders::error,  
  28.             boost::asio::placeholders::bytes_transferred           
  29.         )  
  30.     );  
  31. }  


这个并不是asio的限制,底层套接字的一些函数,如send等也无法保证一次异步操作就把所有的数据都通过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.


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM