0

私のプロトコルは非常に簡単ですsize_t。体のサイズを示すメッセージを送信し、次に体自体を送信しました。

コードは、公式の Boost の例に基づいています。

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_-一部のデータが失われたり、上書きされたりしますか?

4

1 に答える 1

2

buffer_.commit()「返されたオブジェクトは、入力シーケンスまたは出力シーケンスを変更する basic_streambuf メンバー関数によって無効にされprepare()ます。」

実際には、バッファーを手動で準備して chain する代わりにasync_read_some()、適切なヘルパー free 関数とstreambuf完了条件を使用できます。

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

この方法handle_readは、メッセージ本文全体を取得するか、エラーが発生したときに呼び出されます。

于 2013-03-17T09:59:13.213 に答える