2013-03-17 68 views
0

我的協議非常簡單:我發送了一個size_t,指示身體的大小,然後是身體本身。通過boost發送大型身體:: asio :: tcp :: ip

的代碼是基於official Boost examples,那就是:

class tcp_conn : 
     public std::enable_shared_from_this<tcp_conn>, 
     private boost::noncopyable 
    { 
    public: 
     tcp_conn(ba::io_service& io_service); 
     void start(); 
     void stop(); 

     tcp::socket& socket(); 

    private: 
     void handle_read_header(const error_code& e, std::size_t bytes_transferred); 
     void handle_read(const error_code& e, std::size_t bytes_transferred); 

     ba::streambuf::mutable_buffers_type buffer_wrapper_; 
     ba::streambuf buffer_; 
     std::size_t buffer_size_; 
     tcp::socket socket_; 

}; 

和實現是:

void tcp_conn::start() { 
    socket_.async_read_some(
     ba::buffer(&buffer_size_, sizeof(buffer_size_)), 
     boost::bind(
      &tcp_conn::handle_read_header, 
      this, 
      ba::placeholders::error, 
      ba::placeholders::bytes_transferred 
     ) 
     ); 
} 

void tcp_conn::handle_read_header(const boost::system::error_code& e, std::size_t bytes_transferred){ 
    if(!e) { 
     buffer_wrapper_ = buffer_.prepare(buffer_size_); 

     socket_.async_read_some(
      ba::buffer(buffer_wrapper_), 
      boost::bind(
       &tcp_conn::handle_read, 
       this, 
       ba::placeholders::error, 
       ba::placeholders::bytes_transferred 
      ) 
      ); 

    } else { 
     //stop connection 
    } 
} 


void tcp_conn::handle_read(const boost::system::error_code& e, std::size_t bytes_transferred) { 
    if (!e) { 
     buffer_.commit(bytes_transferred); 

     if(buffer_.size() == buffer_size_) { 
      std::cout << "WHOLE BODY TRANSFERED NOW" << std::endl; 
      //has all data in buffer, handle it. 
     } 
     else { 
      std::cout << "NOT WHOLE BODY TRANSFERED, still got "<< (buffer_size_ - bytes_transferred) << " to go" << std::endl; 
      socket_.async_read_some(
       ba::buffer(buffer_wrapper_), 
       boost::bind(
        &tcp_conn::handle_read, 
        this, 
        ba::placeholders::error, 
        ba::placeholders::bytes_transferred 
       ) 
       ); 
     } 


    } 
    else { 
     //handle error 
    } 
} 

這完全不是那麼回事。我猜我的錯誤是在buffer_wrapper_的遞歸更新中的某處 - 某些數據丟失,被覆蓋?

回答

2

buffer_.commit()無效的prepare()的結果,如記錄:其實"The returned object is invalidated by any basic_streambuf member function that modifies the input sequence or output sequence."

,而不是手動準備緩衝區和鏈async_read_some(),你可以只使用與streambuf適當的無輔助功能和完成情況:

asio::async_read(
    socket_, 
    buffer_, 
    asio::transfer_exactly(buffer_size_), 
    boost::bind(&tcp_conn::handle_read, this, _1, _2) 
); 

這種方式handle_read在獲得整個消息正文或發生錯誤時被調用。

+0

嘿謝謝。我只是使它與複雜的手動緩衝區更新工作..你的答案几乎是完美的,但你可以提供所有名稱空間前綴到上述代碼(其中_1,_2,transfer_exactly等定義?) – Queequeg 2013-03-17 10:18:30

+0

@Queequeg'transfer_exactly '在'asio'命名空間中,'_1','_2'綁定佔位符位於全局命名空間中(您可以繼續使用asio佔位符,就像在你的問題中一樣)。 – 2013-03-17 10:22:34

+0

非常感謝,現在更清潔!它**不會工作** :) – Queequeg 2013-03-17 10:24:49

相關問題