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