唯一の問題は、クライアントがすべてを受信したかどうかをサーバーが認識しないことです。状況はあいまいです。クライアントが全体の応答を受け取ったためにクライアント接続がリセットされたのですか、または何らかの理由でリセットされましたか?
アプリケーションレベルの肯定応答を追加しても、問題は確実に解決されません。クライアントが確認応答し、すぐに中止すると、クライアントは、サーバーがその確認応答を受信したことを確認することができません。なぜなら、異常終了は送信されなかったデータを破棄するからです。さらに、データが送信されたとしても、接続が信頼できないためにデータが失われる可能性があります。接続が中止されると、TCPスタックはもはやそのデータの再送信を提供しなくなります。
通常の中断のない状況では、クライアントとサーバーのTCPスタックがアプリケーションの実行とは独立して最終的な儀式を処理することによって問題が解決されます。
要約すると、クライアントが応答を受信し、サーバーが成功したかどうかはサーバーが気にすることではなく、多くの状況では不合理な前提ではありません。
TIME_WAITがサーバー上にあると間違っていると思います。
あなたは、単一のTCPベースのクライアント・サーバ・トランザクションのために、以下の手順に従った場合、TIME_WAITは、クライアント側にある:
クライアントがサーバー
クライアントへのアクティブな接続を開始しますサーバーに要求を送信します。
クライアントは、EOF(FINセグメント)
サーバーが応答して閉じ(FINを生成する)
を送信するまでの接続(つまり、FINを送信します)
サーバはクライアントの要求を読み込み、ハーフクローズ
クライアントはEOFへの応答を読み取ります
クライアントが終了します。
クライアントがFINを最初に送信したので、TIME_WAITに入ります。
トリックは、クライアントが最初に送信方向を閉じる必要があり、サーバーは要求全体を読み取ることによってサーバーを同期させることです。つまり、ストリームの境界をメッセージの境界として使用します。
あなたがしようとしているのは、アプリケーションプロトコルの中だけで要求フレームを作成し、TCPフレームをまったく使用しないことです。すなわち、サーバは、クライアントが終了していないクライアントメッセージの終わりを認識し、同様に、クライアントは終わりまで読書を気にせずにサーバ応答を解析する。
あなたのプロトコルがこのようなものであっても、半分のダンスルーチンの動作を引き続き行うことができます。クライアント要求を取得した後でも、サーバは、バイトが必要ない場合でも、ソケットからの読み取りを維持し、すべてを読み取るまでバイトを破棄することができます。
出典
2016-06-23 14:12:53
Kaz
私はこれが本当だと思っています。サーバーが応答を受信することに興味がない場合(とにかくエラーに反応できないため、HTTPを参照)、リセットソリューションをもっと好きですか? – boot4life
クライアントが応答を受け取っていない場合や、クライアントが応答を受信しなかった場合は、UDPを使用してください(応答が大きすぎないと仮定して) – JvO
大きなメッセージとフロー制御が必要です。しかし、提案をありがとう。 – boot4life