2

クライアントからのTCP接続を受け入れ、クライアントがデータを送信することを決定するまでソケットで待機するC++ネットワークアプリケーションがあります(長時間何も送信しない場合がありますが、それで問題ありません)。

ほとんどの場合、クライアントがクラッシュしたり、マシンの電源が切られたりしたときにエラー状態を検出しますが、クライアントへのネットワーク ケーブルが抜かれたときに気付くのに何分もかかるため、できるだけ早くこの状態に気付くことを望んでいます。

クライアントを制御できず、クライアントに「ping」などを送信させることはできません。私のサーバーはクライアントに「ping」パケットを送信しますが(ただし、クライアントは応答を送信しません)、ケーブルが取り外されていても、write()は正しいバイト数を返します(TCPスタックが再試行を送信していることがわかります) Wireshark のパケット)。

接続が失われたことを通知する最良の方法は何ですか? write() 呼び出しで検出できれば最も便利です。

これは、Windows と Linux で動作する必要があります。

4

3 に答える 3

3

申し訳ありませんが、ping/キープアライブなしで異常な切断をタイムリーに検出する方法はありません。OSでさえ、ケーブルが引っ張られたことを常に認識しているわけではありません。そのため、write()引き続き機能します。ソケットの状態はOSによってまだ無効にされていないため、ソケットは送信バッファーにデータを正常にバッファリングし、後で送信するのを待機しています。最終的に、ソケットは内部でタイムアウトになります。その時点で、OSは最終的に接続を無効にし、ソケットに後続の操作でエラーを報告させることができます。しかし、お気づきのように、これには長い時間がかかる場合があります。

アプリケーション層のpingを送信することはできないため、少なくともソケット層のキープアライブを有効にしてみてください。それが役立つかもしれません。Windows 2000+でのみ、をSIO_KEEPALIVE_VALS介してソケットオプションをWSAIoctl()使用できます。これにより、キープアライブの実際のタイマー値を設定できます。すべてのプラットフォームで、をSO_KEEPALIVE介してオプションを使用できsetsockopt()ますが、タイマー値を構成できないため、代わりにデフォルトが使用されます。

于 2013-01-09T01:45:05.827 に答える
3

残念ながら、もう一方の端でケーブルが引き抜かれていることと、パケット損失の他の理由を区別する方法はありません。そうは言っても、相手側での接続の損失は、十分に長い期間 (T とします) にわたって発生する「無期限のパケット損失」として概算できます。TCP はパケット損失を追跡するため、これを行うための一般的なアプローチは次のようになります。

  • 接続で未確認のバイト数を取得します (B とします)
  • 送信データ、サイズ = N
  • タイムアウト = T を設定し、起動したら、未確認のバイト数を再度確認します。B+N の場合は、相手側が接続を失ったと想定します。この時点で、ICMP エコーを試して、想定を検証できます。

接続の TCP 固有の情報を取得することは、UNIX の標準インターフェイスではなく、Windows に移植できるものでもありません。Linux には、getsockopt() 経由で呼び出すことができる TCP_INFO と呼ばれるソケット オプションがあります。Googleはいくつかの例を提供する必要があります。Windowsに同等のオプションがあるかどうかはわかりません。

これを行う別の方法 (つまり、接続損失のおおよその追跡) は、RAW ソケットを使用することです。RAW ソケットを開き、フィルタリングして、接続の TCP トラフィックのみを受信します。次に、TCP から情報を取得して相手から何かを取得しているかどうかを判断するのではなく、単に相手側からパケットを受信するのを待ちます。規定された期間内に何かを取得した場合、それはピアがまだ稼働していることを意味します。

于 2013-01-09T02:16:36.660 に答える
1

あなたの質問は非常に複雑です。あなたとクライアントの間でうまくいかないことがたくさんあります。単なる「プラグを抜いた」ケーブルではありません。

ユーザーがまだオンラインかどうかを知りたいだけの場合は、新しい TCP 接続を構築できます。TCP 接続を正常に構築するには 3 ウェイ ハンドシェイクを完了する必要があるため、接続が正常に初期化されると、クライアントがオンラインであることがわかります。これに関する問題は、現在の接続をアクティブに保ちたい場合は、別のポートが必要になることです。これがあなたの場合の問題かどうかはわかりません。

しかし、実際にはクライアントからデータを送受信しているわけではありません (一部の ping データは別として)。したがって、単純にアプリケーションをループに設定して、TCP 接続をセットアップすることができます (最初の 2 つのステップ (つまり、ACK を受信すること) で、クライアントがまだネットワーク データを処理しているかどうかを判断するのに十分なはずです)。Xミリ秒以内に応答が得られない場合、クライアントまたはその間の何かが「動作」を停止したとかなり確実に言えます。

お役に立てれば。そうでない場合は、ツールが何をしているかについての詳細を教えてください。

于 2013-01-09T01:48:04.760 に答える