3

古いネットワーク層ライブラリを再実装していますが、今回はboost asioを使用しています。私たちのソフトウェアは、サードパーティのソフトウェアと対話する tcpip です。いくつかのメッセージは両側で非常にうまく動作しますが、私が誤解しているケースが 1 つあります。

サードパーティは 2 つのメッセージ (メッセージ A と B) を次々に送信しますが (実際には短いタイミング)、tcp-packet 1 でメッセージ A の一部のみを受信し、tcp-packet でメッセージ A の最後とメッセージ B 全体を受信します。パケット 2. (wireshark でスニッフィング)。

私はこのケースについて考えたことがありませんでした.tcpで一般的であるかどうか、そして私のレイヤーがそのケースに適応する必要があるかどうか疑問に思っています.異なるパケットのメッセージ。

4

3 に答える 3

4

はい、これはよくあることです。TCP/IP はストリーミング プロトコルであり、「論理」パケットは多くの「物理」パケットに分割される可能性があるため、クライアントは上位レベルのパケットを組み立てる必要があります。さらに、TCP/IP は適切な順序を保証するため、順不同のパケットの組み立てについて心配する必要はありません。

于 2012-11-19T15:42:09.513 に答える
4

パケットはフラグメント化され、順不同で到着する可能性があります。それらを受信する TCP スタックは、データを着信ストリームとしてアプリケーション層に提示する前に、それらをバッファリングして並べ替える必要があります。

私の問題は、同じパケット内のメッセージ 1 の終了後であるため、表示されないメッセージ B にあります。

「パケット」への 1 対 1 のマッピングを持つ「メッセージ」に依存することはできません。アプリケーションにとって、TCP (UDP ではない) は「ストリーミング」プロトコルのように見えます。

TCP 経由で送信するアプリケーションには、メッセージを分離する別の方法が必要です。場合によっては、各メッセージの終わりをマークすることでそれが行われます。たとえば、SMTPはメッセージの終わりを次のようにマークします。

メールメッセージの本文の送信は、DATA コマンドで開始され、その後、行ごとに逐語的に送信され、データの終わりのシーケンスで終了します。このシーケンスは、改行 ()、単一のピリオド (ピリオド)、およびそれに続く別の改行で構成されます。メッセージ本文にはテキストの一部としてピリオドのみを含む行を含めることができるため、クライアントは行がピリオドで始まるたびに 2 つのピリオドを送信します。それに応じて、サーバーは行頭の 2 つのピリオドのすべてのシーケンスを 1 つのピリオドに置き換えます。このようなエスケープ方法は、ドット スタッフィングと呼ばれます。

あるいは、プロトコルは各メッセージの開始時にプレフィックスを指定する場合があり、これはメッセージの長さをバイト単位で示します。

TCP スタックをコーディングしている場合は、 TCP メッセージ ヘッダーにアクセスできます。「データ オフセット」フィールドは、各メッセージの長さを示します。

于 2012-11-19T15:43:16.570 に答える
3

あなたの問題はTCPとはまったく関係ありません。あなたの問題は、asio がメッセージの解析を行うことを期待していたことです。そうではありません。実装する必要があります。

  • メッセージがすべて同じサイズの場合、そのサイズの非同期読み取りを行います。
  • それらの長さが異なる場合は、ヘッダー サイズの非同期読み取りを実行し、ヘッダーを分析して、ヘッダーに従ってメッセージの残りの部分を非同期読み取りを実行します。
  • メッセージが可変長でサイズが不明であるが、定義された終了文字またはシーケンスがある場合、その終了シーケンスの後ろに残りのバイトを保存し、次の読み取りをその残りに追加する必要があります。
于 2012-12-08T20:37:02.180 に答える