2013-02-25 12 views
6

私はパケットの送受信に以下の2つの機能を持っています。boost :: asio :: buffer:バッファサイズの取得とバッファオーバーフローの防止?

void send(std::string protocol) 
{ 
    char *request=new char[protocol.size()+1]; 
    request[protocol.size()] = 0; 
    memcpy(request,protocol.c_str(),protocol.size()); 

    request_length = std::strlen(request); 
    boost::asio::write(s, boost::asio::buffer(request, request_length)); 
} 
void receive() 
{ 
    char reply[max_length]; 
    size_t reply_length = boost::asio::read(s, boost::asio::buffer(reply, request_length)); 
    std::cout << "Reply is: "; 
    std::cout.write(reply, reply_length); 
    std::cout << "\n"; 
} 

質問は、要求の長さは、パケットが送られたとき、最初に設定した文字列の長さであるこの部分boost::asio::buffer(reply, request_length)に関係します。 request_lengthを知らずにバッファのサイズを確認するにはどうすればよいですか?別の問題は、バッファオーバーフローを防ぐ方法です。

答えて

15

バッファのサイズを取得するには、boost::asio::buffer_size()関数を使用できます。しかし、あなたの例では、これはあなたにほとんど役に立たないでしょう。

バッファーoverviewで説明したように、Boost.Asioはバッファーを表すバッファークラスを使用します。これらのクラスは抽象化を提供し、バッファオーバーランに対するBoost.Asio操作を保護します。 boost::asio::buffer()の結果は操作に渡されますが、バッファのサイズやその基礎となる型などのメタデータは送信されません。また、これらのバッファはメモリを所有していないため、バッファ抽象化の存続期間中、基礎となるメモリが有効であることを保証するのはアプリケーションの責任です。

boost::asio::buffer()関数は、バッファクラスを作成する便利な方法を提供します。バッファクラスのサイズは、可能な型から推測されます。 Boost.Asioがバッファの長さを推測することができる場合、Boost.Asioオペレーションは結果のバッファタイプを使用するときにバッファオーバーフローを呼び出すことはありません。しかし、アプリケーションコードがバッファのサイズをboost::asio::buffer()に指定している場合は、そのサイズが基礎となるメモリより大きくないことをアプリケーションが保証する必要があります。

データを読み取るときは、バッファが必要です。基本的な質問は、Boost.Asioがサイズを送信しない場合、どのくらいのメモリを割り当てるべきかを知ることになります。

  • クエリsocket::available()を経由して提供されていますどのくらいのデータ、それに応じてバッファを割り当てるためのソケット:この問題にはいくつかのソリューションがあります。

    std::vector<char> data(socket_.available()); 
    boost::asio::read(socket_, boost::asio::buffer(data)); 
    
  • Boost.Asioは、boost::asio::streambufとして、メモリに成長することができますクラスを使用します。 boost::asio::read()などの一部の操作は、オブジェクトとしてバッファーとしてstreambufを受け入れ、操作に必要なメモリーを割り当てます。ただし、完了条件を提示する必要があります。それ以外の場合は、バッファがいっぱいになるまで操作は続行されます。 Öö Tiibとして

    boost::asio::streambuf data; 
    boost::asio::read(socket_, data, 
            boost::asio::transfer_at_least(socket_.available())); 
    
  • 通信プロトコルの一部として長さを組み込んで、示唆しています。通信プロトコルの例については、Boost.Asio examplesを参照してください。プロトコルに焦点を当て、必ずしもブーストではない。Asio API

    • 固定サイズのプロトコルでは、データプロデューサとコンシューマは同じサイズのメッセージを使用します。読者はメッセージのサイズを知っているので、読者は事前にバッファを割り当てることができる。
    • 可変長プロトコルでは、メッセージは多くの場合、ヘッダーと本文の2つの部分に分割されます。ヘッダーは通常は固定サイズであり、本文の長さなどのさまざまなメタ情報を含むことができます。これにより、読者はヘッダを固定サイズのバッファに読み込み、ボディの長さを抽出し、ボディのバッファを割り当ててから本文を読み込むことができます。

      // Read fixed header. 
      std::vector<char> data(fixed_header_size); 
      boost::asio::read(socket_, boost::asio::buffer(data)); 
      
      protocol::header header(data); 
      network_to_local(header); // Handle endianess. 
      
      // Read body. 
      data.resize(header.body_length()); 
      boost::asio::read(socket_, boost::asio::buffer(data)); 
      
      protocol::body body(data); 
      network_to_local(body); // Handle endianess.  
      
+0

素晴らしいもの。 'boost :: asio :: read_until()'を使った 'boost :: asio :: streambuff'は、メッセージがデリミタで終わる場合にはうまくいきました。 –

1

私はあなたの質問が混乱していると思いますが、これは役立つかもしれない:

void receive() { 
    enum { max_length = 1024 }; 
    char reply[max_length]; 
    size_t reply_length; 
    std::cout << "Reply is: "; 
    while ((reply_length = ba::read(s, basio::buffer(reply, max_length))) > 0) { 
    std::cout.write(reply, reply_length); 
    } 
    std::cout << "\n"; 
} 
+0

'ブースト:: ASIO ::バッファ(、)'正確に何を返します。私はそれが 'ba :: read(s、buffer(、))'に何かを返すのを見ますが、それは何ですか? – pandoragami

+0

@lost_with_coding:メモリを表しますが、メモリを所有していないタイプです。 [関数](http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/buffer.html)は、一般的に使用される型を、ブーストの多くの型要件を満たすように適合させるのに役立ちます.Asio操作。この[概要](http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/overview/core/buffers.html)にはいくつかの情報があります。 –

+0

この例では、max_lengthをasio :: buffer()に渡す必要はありません。 (asioは 'sizeof'を使ってそれを得ることができるので) –

5

通常の通信プロトコルは、メッセージの長さを指示するヘッダが含まれている固定長のメッセージやメッセージを使用していますどちらか。

Boost.Asio online documentationには多数のサンプルとチュートリアルが含まれていますので、そこから始めてください。 Wikipediaはdata transmissionという用語を説明するのに良いソースです。

+1

私は既にboost asioチュートリアルを見てきましたが、例を詳しく見ていて、関数が何をしているか、返すものなどを詳しく説明しません。私はhppファイルも見ることができると知っていますが、それは乾草の針のようであり、例そのものよりも無駄です。 PLus私はブーストの例やチュートリアルでは言及されていないが、消費するには何年もの練習が必要なhppファイルでしか見つからないことがたくさんあると確信しています。 – pandoragami

+0

@lost_with_codingおそらく、ブーストasioの例では、人々はデジタル通信の概念と、プロトコール、クライアント、サーバー、要求などのような関連用語の意味を例に熟知していることを期待しています。私は、コードからそのような知識をリバースエンジニアリングすることを推奨します。 –

+0

@lost_with_coding:[examples](http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/examples.html)では、APIの機能については説明していません。これは[reference ](http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference.html)セクションを参照してください。 Boost.Asioライブラリは複雑で複雑ではありません。ドキュメントには大量の情報があり、ドキュメントのさまざまな部分に慣れるために時間をかけておく価値があります。 –

関連する問題