2011-06-24 10 views
2

私は、C++でアプリケーション間のネットワーク接続を維持するライブラリを構築しています。いくつかのデバッグ中に私はソケットから取得するいくつかの情報が不完全であることがわかりました。プロトコルバッファのライブラリでデコードすれば、完全なメッセージが必要なので、この情報は完全であることが不可欠です。tcp/ipは完全なメッセージを伝えますか?

現象は一定ではありません。ときには、ソケットからすべてのデータを取得することもあります。テストの手順は、サーバーの起動、クライアントの複数回の起動のようになります。私が得るものは、関数から出力され、いくつかの変数の値がどのように変化するかを表しています。それらの1つは、データを格納するために使用するバッファのサイズです。そのサイズは、バッファ内のデータ量を示します。クライアントは、この特定のテストでサイズ3(バイト)のメッセージをそれぞれ2回送信します。私は、バッファサイズが3の倍数になることを期待しています。しかし、時々サイズは4です!これは、プログラムが1つの完全なメッセージと2つ目のメッセージの1/3を読み込むことを意味します。なぜ私はいつも最初のメッセージを完成させるのか分からない。それ以外の場合、protobufはプログラムを終了します。

私はtcp/ipは私が完全なメッセージを得るように気を付けるべきだと思った。私の問題は、サイズをあらかじめ知っていないことです。私は完全なメッセージを受け取って、それを中核と解釈することができると期待しています。

答えて

9

TCPはストリームベースのプロトコルであり、メッセージベースのプロトコルではありません。 TCPはあなたのメッセージの開始と終了を知らないので、1回の呼び出しで完全なメッセージを受け取ることはできません。 1つの完全なメッセージが得られるという保証もありません。あなたは受け取ったデータをバッファリングし、あなた自身のメッセージに分割する必要があります。完全なメッセージが得られない場合は、受信したデータを保存し、残りのデータが到着するまで待ちます。

2

TCPは、受信者の中で、順番に組み立てされている複数のデータグラム、へフラグメントあなたのデータに許可されています。データは、送信された順に最終的に到着することが保証されます。しかし、送信するデータの一部は、残りの部分より早く到着する可能性があります。

receiveに電話すると、送信したデータの一部がコンピュータに届いていますが、その一部がネットワーク経由で送信されている可能性があります。受信したデータの一部をバッファして、完全な "メッセージ"を受信するまで待つ必要があります。これを処理できる方法の1つは、メッセージの残りのバイトの長さをエンコードする、各メッセージの先頭に固定長のレコードを送ることです。たとえば、ネットワークバイトオーダーで4バイトの符号なしlongを送信した後、その数バイトのデータを送信することができます。

関連する問題