2016-06-23 17 views
1

TIME_WAIT問題の解決策として、TCP接続をリセットする方法を検討しています。アプリケーションレベルの肯定応答を受信した後でTCP接続をリセットすることはできますか?


のは、一例として、以下の要求 - 応答プロトコルを使用してみましょう:

  1. クライアントがサーバーへの接続をオープンします。
  2. クライアントから要求が送信されます。
  3. サーバーが応答します。
  4. サーバーが終了します。
  5. クライアントも閉じます。

これにより、サーバーにTIME_WAIT状態が発生します。バリエーションとして、クライアントは最初に閉じることができます。その後、TIME_WAITがクライアントに到着します。

手順4と5を次のように置き換えることはできませんか?

  1. クライアントがリセットされます。
  2. 受信リセットに応答してサーバーがリセットされます。

これはTIME_WAITの問題を回避する方法のようです。サーバーは、応答を送信して要求を受信して​​処理したことを証明しました。クライアントが応答を受け取ると、接続は消耗して、ただ消えるだけです。

これは良い考えですか?

答えて

1

唯一の問題は、クライアントがすべてを受信したかどうかをサーバーが認識しないことです。状況はあいまいです。クライアントが全体の応答を受け取ったためにクライアント接続がリセットされたのですか、または何らかの理由でリセットされましたか?

アプリケーションレベルの肯定応答を追加しても、問題は確実に解決されません。クライアントが確認応答し、すぐに中止すると、クライアントは、サーバーがその確認応答を受信したことを確認することができません。なぜなら、異常終了は送信されなかったデータを破棄するからです。さらに、データが送信されたとしても、接続が信頼できないためにデータが失われる可能性があります。接続が中止されると、TCPスタックはもはやそのデータの再送信を提供しなくなります。

通常の中断のない状況では、クライアントとサーバーのTCPスタックがアプリケーションの実行とは独立して最終的な儀式を処理することによって問題が解決されます。

要約すると、クライアントが応答を受信し、サーバーが成功したかどうかはサーバーが気にすることではなく、多くの状況では不合理な前提ではありません。

TIME_WAITがサーバー上にあると間違っていると思います。

あなたは、単一のTCPベースのクライアント・サーバ・トランザクションのために、以下の手順に従った場合、TIME_WAITは、クライアント側にある:

  1. クライアントがサーバー

  2. クライアントへのアクティブな接続を開始しますサーバーに要求を送信します。

  3. クライアントは、EOF(FINセグメント)

  4. サーバーが応答して閉じ(FINを生成する)

    を送信するまでの接続(つまり、FINを送信します)

  5. サーバはクライアントの要求を読み込み、ハーフクローズ

  6. クライアントはEOFへの応答を読み取ります

  7. クライアントが終了します。

クライアントがFINを最初に送信したので、TIME_WAITに入ります。

トリックは、クライアントが最初に送信方向を閉じる必要があり、サーバーは要求全体を読み取ることによってサーバーを同期させることです。つまり、ストリームの境界をメッセージの境界として使用します。

あなたがしようとしているのは、アプリケーションプロトコルの中だけで要求フレームを作成し、TCPフレームをまったく使用しないことです。すなわち、サーバは、クライアントが終了していないクライアントメッセージの終わりを認識し、同様に、クライアントは終わりまで読書を気にせずにサーバ応答を解析する。

あなたのプロトコルがこのようなものであっても、半分のダンスルーチンの動作を引き続き行うことができます。クライアント要求を取得した後でも、サーバは、バイトが必要ない場合でも、ソケットからの読み取りを維持し、すべてを読み取るまでバイトを破棄することができます。

+0

私はこれが本当だと思っています。サーバーが応答を受信することに興味がない場合(とにかくエラーに反応できないため、HTTPを参照)、リセットソリューションをもっと好きですか? – boot4life

+0

クライアントが応答を受け取っていない場合や、クライアントが応答を受信しなかった場合は、UDPを使用してください(応答が大きすぎないと仮定して) – JvO

+0

大きなメッセージとフロー制御が必要です。しかし、提案をありがとう。 – boot4life

1

私はこう言っています。いいえ、それは良い考えではありません。すべての可能な解決策は、最終的に解決するのと同じ「問題」で終わります。パーティーAは、接続の終了を認識するか(または相手方が接続の終了を確認したかを確認する)、パーティBが承認を得たことを知っていますか? ?答えはいつもあります。確かにそのことを知ることはできません。

あなたが言う:

は、サーバがその応答

を送信することにより、要求を受信し、処理することを証明している...しかし、その応答が失われたらどう?サーバーはセッションの面をクリーンアップしましたが、クライアントはその応答を永遠に待っています。

一見するとTCP状態マシンはあまりにも複雑に思えるかもしれませんが、それはすべて正当な理由でそのように行われます。

+0

クライアントは返信を受け取った後に*リセットするものです。応答が到着しない場合、通常の接続切断機構が機能します。 – boot4life

+0

あなたはまだ最後の*メッセージ*(リセット、返信、承認など)を送信して、もう一方の側が実際にその最後のメッセージを受け取ったことを確かに知ることはできません。それが 'TIME_WAIT'のすべてです。 –

+0

メッセージが受信されたことを決して確かめることはできず、すべての場合に何が起こったのかを決して確かめることはできません(2つの一般問題を参照)。 – boot4life

関連する問題