2012-02-17 37 views
2

私は同期ブーストアシオを使用して読み取り/書き込みを行っています。データは境界なしでバイナリ形式で送られ、長さ情報はパケット形式で符号化されます。したがって、指定されたサイズで読み込むことが重要です。 ip::tcp::iostreamできますか?誰かが例を挙げることはできますか?ありがとう。boost asioを使用してフィックスサイズのパケットを読み取る方法は?

+0

あなたはどういう意味ですか?プロトコルのフレーミングは通常アプリケーションレベルで行われますが、データのストリームではなくパケットについて考えることで混乱していると思います。 –

答えて

1

異なるサイズの異なるデータを送信するプログラムで動作します。私はサイズを取得

enum { header_length = 8 }; //const header length 

//give header length  
std::ostringstream header_stream 
header_stream << std::setw(header_length) //set a field padding for header 
       << std::hex     //set next val to hexadecimal 
       << m_data_out.m_outbound_data.size(); //write size in hexa 

m_data_out.m_outbound_header = header_stream.str(); //m_outbound_head == size in hexa in a std::string 

     //m_outbound_header = [ 8 byte size ] 
     //m_outbound_data = [ serialized data ] 

     //write all data in the std::vector and send it 
     std::vector<boost::asio::const_buffer> buffer; 
     buffer.push_back(boost::asio::buffer(m_data_out.m_outbound_header)); 
     buffer.push_back(boost::asio::buffer(m_data_out.m_outbound_data)); 
(m_outbound_dataはスタンダード::文字列==シリアライズオブジェクトれる):Iサイズをエンコードするために8バイトの固定ヘッダを使用し、その後、私は、データを追加します

そして読書のために、あなたは2時間に読む必要がある:第一の大きさを得るために8バイトを読み、その後、ベクトル内のデータを読み取り、オブジェクトにデシリアライズ:

struct network_data_in { 
    char m_inbound_header[header_length]; //size of data to read 
    std::vector<char> m_inbound_data; // read data  
}; 

私がデータを取得するために、この構造体を使用し、記入するためにm_inbound_headerでreadを呼び出すサイズのバッファが最初に、そして、ハンドルに:

//get size of data 
std::istringstream is(std::string(m_data_in.m_inbound_header, header_length)); 
std::size_t m_inbound_datasize = 0; 
is >> std::hex >> m_inbound_datasize; 
m_data_in.m_inbound_data.resize(m_inbound_datasize); //resize the vector 

、バッファ上のm_inbound_dataで読み取る再び呼び出して、正確にデータを読み出す。この結果は、あなたがデータをデシリアライズする必要がありジュスト二handle_readで を送りました。

//extract data 
std::string archive_data (&(m_data_in.m_inbound_data[0]),m_data_in.m_inbound_data.size()); 
std::istringstream archive_stream(archive_data); 
boost::archive::text_iarchive archive(archive_stream); 
archive >> t; //deserialize 

希望はあなたを助けよう!

+0

+1良い答え、これは私が提案するものです。フィックス長ヘッダーを含めるようにプロトコルを変更します。あなたのプロトコルを変更することができない場合は、質問にそのように述べてください。 –

1

TCPはストリームベースのプロトコルです。つまり、読んだものは単なるバイトストリームです。 例を考えてみましょう。固定サイズのメッセージがあり、それをTCP経由で送信します。他端のプログラムはどのようにしてメッセージ全体を読むことができますか? 2つの方法があります.1つは、制御の仕方でメッセージを囲むことです(開始時にはSTX、最後にETXなど)。最初に、プログラムはSTXの前に任意の文字を破棄し、ETXに遭遇するまで他の文字をメッセージバッファに読み込みます。

もう1つの方法は、メッセージ長を固定長のヘッダーにエンコードすることです(これはあなたのケースです)。したがって、メッセージの長さを読み取って解析し、それに応じて残りのバイトを読み取る方法を見つけ出すことが最善の方法です。

+1

私は長さの情報が必要であることを理解しています。明確ではないのは、この長さ(読みたいバイト数)をAPIで指定することです。 – Oliver

+0

@Oliverあなたのコメントは理にかなっていません。読み込むバイト数は、APIの[boost :: asio :: read'](http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio/reference/read/)のようによく記述されています。 overload1.html) –

1

シンプル:*長さ情報はパケット形式でエンコードされた*:

boost::asio::read(socket, buffers, boost::asio::transfer_exactly(your_fixed_size)); 
関連する問題