私は、ソケットクラスの非同期メソッド(BeginAccept()、BeginReceive()など)を使用するかなり汎用的なC#ソケットサーバーを持っています。このサーバーは、WinServer2003を実行している多くの顧客サイトで過去4年間うまく機能しています。 Windows Server 2008 R2サーバー、64ビットにインストールしました。最初のクライアントが接続し、acceptハンドラーでBeginReceive()およびBeginAccept()呼び出しを発行するまで、すべてが正常に見えます。これが発生すると、CPU使用率が100%に急上昇し、リスニングソケットを閉じるまでその状態が続きます。
重要かどうかはわかりませんが、サーバーは仮想マシンで実行されています。
多くのテストを行いましたが、何も役に立たないようです。Process Explorerを使用すると、BeginReceive()/ BeginAccept()呼び出しの直後に2つのスレッドがスピンアップし、それらがプロセッサーを消費していることがわかります。残念ながら、Win764ビットワークステーションではこの問題を再現できません。
私は多くの調査を行いましたが、これまでに見つけたのは、Server2008R2でTCP/IPコンポーネントに問題がある可能性があることを示唆する、次の2つのKB記事ですが、これらはホットフィックスとしてのみ入手可能です:KB2465772およびKB2477730。問題が解決することが確実になるまで、顧客にインストールしてもらうのは気が進まない。
他の誰かがこの問題を抱えていましたか?もしそうなら、あなたはこの問題を解決するために何をしなければなりませんでしたか?
これが状況を引き起こすと私が信じる方法です:
private void AcceptCallback(IAsyncResult result) {
ConnectionInfo connection = new ConnectionInfo();
try {
// Finish accept.
Socket listener = (Socket)result.AsyncState;
connection.Socket = listener.EndAccept(result);
connection.Request = new StringBuilder(256);
// Start receive and a new accept.
connection.Socket.BeginReceive(connection.Buffer, 0,
connection.Buffer.Length, SocketFlags.None,
new AsyncCallback(ReceiveCallback), connection);
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), listener);
// CPU usage spikes at 100% shortly after this...
}
catch (ObjectDisposedException /*ode*/) {
_log.Debug("[AcceptCallback] ObjectDisposedException");
}
catch (SocketException se) {
connection.Socket.Close();
_log.ErrorFormat("[AcceptCallback] Socket Exception ({0}: {1} {2}", connection.ClientAddress, se.ErrorCode, se.Message);
}
catch (Exception ex) {
connection.Socket.Close();
_log.ErrorFormat("[AcceptCallback] Exception {0}: {1}", connection.ClientAddress, ex.Message);
}
}