2

シナリオは、ホーム ネットワーク上の TCP を介して、あるマシンから別のマシンにデータを送信することです。送信者は をインスタンス化し、によって返されTCPClientた にデータを書き込みます。私の理解では、 のデータは最終的に NIC のバッファに送信され、物理メディアを介して送信されます。NetworkStreamGetStream()NetworkStream

ただし、接続が中断されるMemoryStreamと、NIC バッファー内のデータと NIC バッファー内のデータは失われますが、私のアプリケーションでは、データはストリームに書き込まれ、データがリッスンしているソケットに送信されたと単純に推測できました。 、しかし、明らかにそうではありません。MemoryStream接続が再確立されると、アプリケーションはデータの送信を再開しますが、アプリケーションが知る限り、送信が中断された場合でも、NIC のバッファとオブジェクトで失われたデータは考慮されません。

独自のアプリケーション層プロトコルを作成する以外に、この問題を回避する方法はありますか?

4

2 に答える 2

2

ソケットに書き込まれたデータが到着することが保証されているとしましょう。これは、TCP スタックがすべてのパケットの後に確認を待たなければならないことを意味します。

明らかに、これが機能する方法ではありません。

TCP は、接続を正常に閉じた場合を除き、到着を保証しません。そうして初めて、すべてが受け取られたことがわかります。

おそらく、アプリケーション層で再開プロトコルを確立する必要があります。最初の接続でどこまで到達したかを反対側に尋ねます。

コメントでの多くの議論は、次の明確化につながります。接続が中断された場合、送信者は、相手側が受信したバイト数を確実に知ることができません。彼は、すべてが受信されたわけではなく、受信されたものではないことを確実に知るでしょう.

于 2013-03-18T19:19:16.890 に答える
0

いくつかのオプションがあります。NetworkStream1 つの方法は、おそらく、データのバッチが書き込まれるたびに、データを手動でパイプにフラッシュすることです。

アプリケーションのタイプによっては、これがパフォーマンスの障害点と見なされる場合がありますが、これは最もフォールト トレラントな方法です。を手動で呼び出すことにより.Flush()、データがパイプに正常に送信されたかどうかを知ることができます。

これをバッチで から に実行している場合はMemoryStreamNetworkStream「最後に書き込まれたバイト」を保存して に戻すことができMemoryStream、接続が再確立されたときに再試行できるようになります。

別のオプションは、独自のプロトコルを実装することです。接続時に、サーバーが現在までに受信したバイト数をクライアントにすぐに送信します (つまり、最後の接続以降)。この情報があれば、最初の X バイトMemoryStream(既に送信されたもの) を消去し、残りのデータをプッシュダウンし続けることができます。

あなたができる最後の1つのことは、最良の方法かもしれませんが、2つの組み合わせです. 基本的に送信/確認プロトコルを実装します。つまり、データのチャンクを送信し、サーバーが ACK/OK を返すのを待ちます。受信した場合、サーバーがこのデータを受信したことを確認できますが、受信していない場合は、その ACK を取得するまで再試行を続けることができます。

于 2013-03-18T19:26:11.703 に答える