私は既存の例を研究しました:
- boost::asio を使用した Protobuf メッセージの送信
- boost::asio::read_async を使用して Protobuf オブジェクトを読み取る
- Google プロトコル バッファ: C++ の parseDelimitedFrom と writeDelimitedTo
- Java の Protocol Buffers で区切られた I/O 関数に相当する C++ はありますか?
- boost::asio を使用した Protobuf メッセージの送信
しかし、Boost::asio API を使用して Google Protobuf メッセージを渡す方法がまだわかりません。特に、次の問題について明確な理解がありません。
- boost::asio::streambuf と google::protobuf::io オブジェクト間の相互作用 (および最後のものを適用する必要性)
- メッセージ ストリーミングの正しい実装 (C++ API に writeDelimitedTo および parseDelimitedFrom メソッドがないため)
これは、サンプルのboost::asio v. 1.39 ssl_clientに基づく私の実装です。
class client
{
public:
client(boost::asio::io_service& io_service, boost::asio::ssl::context& context,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
: socket_(io_service, context),
request_stream(&b),
raw_output(&request_stream),
coded_output(&raw_output)
{
...
}
void handle_connect(const boost::system::error_code& error,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
{
...
}
//Debugging function
void print_buffers_condition(const char *step)
{
std::cout << "\nBuffer conditions after " << step << std::endl;
std::cout << "boost::asio::streambuf\t\tb: " << b.size() << std::endl;
std::cout << "google::protobuf::io::OstreamOutputStream raw_output: " << raw_output.ByteCount() << std::endl;
std::cout << "google::protobuf::io::CodedOutputStream coded_output: " << coded_output.ByteCount() << std::endl;
std::cout << std::endl;
}
//Sending test message after SSL Handshake
void handle_handshake(const boost::system::error_code& error)
{
std::cout << "-----------------------------SENDING-----------------------------" << std::endl;
print_buffers_condition("handle handshake");
if (!error)
{
SearchRequest msg;
msg.set_query("qwerty");
msg.set_code(12345);
std::cout << "Debugged" << std::endl;
msg.PrintDebugString();
//Writing the length of the message before and serializing
print_buffers_condition("before serialising");
coded_output.WriteVarint32(msg.ByteSize());
if (!msg.SerializeToCodedStream(&coded_output))
{
std::cout << "serailizing error" << std::endl;
}
else
{
std::cout << "serializing success" << std::endl;
}
//Sending
buffers_condition("before async write");
boost::asio::async_write(socket_,
b,
boost::bind(&client::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
buffers_condition("after async write");
}
else
{
std::cout << "Handshake failed: " << error << "\n";
}
}
void handle_write(const boost::system::error_code& error,
size_t bytes_transferred)
{
std::cout << " bytes_trransferred: " << bytes_transferred << std::endl;
if (!error)
{
std::cout << "No error" << std::endl;
...
}
else
{
std::cout << "Write failed: " << error << "\n";
}
}
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
...
}
private:
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
boost::asio::streambuf b;
std::ostream request_stream;
google::protobuf::io::OstreamOutputStream raw_output;
google::protobuf::io::CodedOutputStream coded_output;
};
このコードは機能するので、メッセージを作成した後、void handle_write(const boost::system::error_code& error, size_t bytes_transferred)
関数に入ります。値を出力bytes_transferred_
すると 0 が返されます: サーバー (例に基づいて実装されています) は何も受信しません。
デバッグ関数の使用は、void print_buffers_condition(const char *step)
さまざまなバッファリング オブジェクトのスタックを介した送信中にメッセージが失われることを示唆しています。
$ ./client 127.0.0.1 5000
-----------------------------SENDING-----------------------------
Buffer conditions after handle handshake
boost::asio::streambuf b: 0
google::protobuf::io::OstreamOutputStream raw_output: 8192
google::protobuf::io::CodedOutputStream coded_output: 0
Debugged:
query: "qwerty"
code: 12345
Buffer conditions after before serialization
boost::asio::streambuf b: 0
google::protobuf::io::OstreamOutputStream raw_output: 8192
google::protobuf::io::CodedOutputStream coded_output: 0
serializing success
Buffer conditions after before async write
boost::asio::streambuf b: 0
google::protobuf::io::OstreamOutputStream raw_output: 8192
google::protobuf::io::CodedOutputStream coded_output: 13
Buffer conditions after after async write
boost::asio::streambuf b: 0
google::protobuf::io::OstreamOutputStream raw_output: 8192
google::protobuf::io::CodedOutputStream coded_output: 13
bytes_trransferred: 0
適切な方法でそれを行う方法がわかりません。OSはRHEL6.4です。ありがとうございました。