2

これには、2つの自動化された単体テストが含まれます。それぞれが非ブロッキングソケットを作成するtcp / ipサーバーを起動し、データを接続してダウンロードするクライアントのselect()のループでbind()とlisten()を実行します。

問題は、個別に実行すると完全に機能することですが、テストスイートとして実行すると、2番目のテストクライアントはWSACONNREFUSEDとの接続に失敗します...

そうでもなければ

それらの間に数秒のThread.Sleep()がありますか?? !!!

興味深いことに、障害が発生した後は、接続のために1秒ごとに再試行ループがあります。したがって、2番目のテストは10分後にタイムアウトするまでしばらくループします。

その間、netstat -naは、サーバーソケットの正しいポート番号がLISTEN状態にあることを示します。それで、それがリッスン状態にある場合はどうなりますか?なぜ接続を受け入れないのですか?

コードには、select NEVERがソケットを読み取る準備ができていないことを示すログメッセージがあります(つまり、リスニングソケットに適用されるときに接続を受け入れる準備ができていることを意味します)。

明らかに、問題は、ソケットの両端でclose()とshutdown()を意味する1つのテストを終了してから、次のテストを開始するまでの競合状態に関連している必要があります。

再試行ロジックによって、数秒後に最終的に接続が許可された場合、これはそれほど悪くはありません。しかし、それは「ぐちゃぐちゃになっている」ようで、再試行すらしません。

ただし、奇妙な理由で、リスニングソケットは、接続を拒否し続けても、リッスン状態にあると言います。

つまり、実際にSYNパケットをキャッチしてRSTパケット(「接続が拒否された」を意味する)を返すのはWindoze O/Sです。

私がこのエラーを目にしたのは、コードに問題があり、何百ものソケットがTIME_WAIT状態でスタックする原因となったときだけでした。しかし、ここではそうではありません。netstatは、任意の時点でTIME_WAITに1つまたは2つしかない約12個のソケットのみを表示します。

助けてください。

4

3 に答える 3

2

根本的な問題は、ソケットを閉じることでした。スレッドは残りのバイトを読み取ろうとしていました。これは、データの読み取りを繰り返し試行しながら、ソケットの読み取り端をミリ秒の固定時間開いたままにする別のスレッドとして実行されました。

このロジックは、データをよりインテリジェントに読み取り、読み取りが0を返したときに適切に閉じるように置き換えられました。したがって、はるかに迅速に閉じられます。

したがって、私自身のコードでは、ソケットを不適切に閉じることが判明しました。

すべての助けをありがとう!

于 2010-05-23T21:06:28.670 に答える
2

さまざまなコア数のさまざまなWindowsオペレーティングシステム(XPからWindows 7)を搭載したビルドマシンでこのようなテストをたくさん実行しましたが、問題になることはありませんでした。

リッスンソケットの移行がTIME_WAIT問題になる可能性は低いと思います。私は確かにそれを見たことがなく、TIME_WAIT遅延期間内にサーバーを起動および停止するのと同じポートでクライアントサーバーテストを定期的に実行しています。

最初のサーバーがソケットを閉じる前に2番目のサーバーを起動していた場合(または、ソケットが入っていた場合TIME_WAIT)、2番目のサーバーでエラーが発生することが予想されますbind()

個人的には、接続を受け入れているコードに問題がある可能性が高いと思います。つまり、テストでバグが見つかった可能性があります;)

listenループとacceptループの間のコードを見てみましょう。

テストの順序を逆にすると問題が発生しますか?

クライアントとサーバーは同じマシンで実行されていますか?そうでない場合は状況が変わりますか?

等。

例に対してそのリンクからテストクライアントを実行するようにテストシステムを設定した場合、いくつかのTCPテストツールhttp://www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.htmlがあります。これからのサーバーhttp://www.lenholgate.com/blog/2005/11/simple-echo-servers.htmlまだ問題がありますか?(つまり、テストシステムでクライアントを使用してサーバーを実行し、サーバーが自分のものを実行するのと同じように実行し、自分のものが機能するようにしますか?)

于 2010-04-25T16:15:06.140 に答える
1

このMSDNサイトから:

TIME_WAIT状態は、TCPが閉じた接続を解放してそのリソースを再利用できるようになるまでに経過する必要がある時間を決定します。クローズとリリースの間のこの間隔は、TIME_WAIT状態または2MSL状態として知られています。この間、新しい接続を確立するよりもはるかに少ないコストで、クライアントとサーバーへの接続を再開できます。TIME_WAITの動作はRFC793で指定されており、TCPはネットワークの最大セグメントライフタイム(MSL)の2倍以上の間隔で閉じた接続を維持する必要があります。接続が解放されると、そのソケットペアと、ソケットに使用される内部リソースを使用して、別の接続をサポートできます。

Windows TCPは、接続が閉じられた後、TIME_WAIT状態に戻ります。TIME_WAIT状態の間は、ソケットペアを再利用できません。TIME_WAIT期間は、TIME_WAIT期間を秒単位で表す次のDWORDレジストリ設定を変更することで構成できます。

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters\TcpTimedWaitDelay

デフォルトでは、MSLは120秒と定義されています。TcpTimedWaitDelayレジストリ設定のデフォルト値は240秒です。これは、120秒または4分の最大セグメントライフタイムの2倍を表します。ただし、このエントリを使用して間隔をカスタマイズできます。このエントリの値を減らすと、TCPは閉じた接続をより速く解放し、新しい接続により多くのリソースを提供できます。ただし、値が低すぎる場合、TCPは接続が完了する前に接続リソースを解放する可能性があり、サーバーは接続を再確立するために追加のリソースを使用する必要があります。このレジストリ設定は、0〜300秒の範囲で設定できます。

値を設定できる最小値は30だと思います(小さくしてみてくださいが、うまくいかない場合があります)

詳細な説明については、WinsockプログラマーのFAQを参照してください。

于 2010-04-25T05:22:17.693 に答える