BeginConnect() を使用して、TCP 接続 (TCP ソケットへの接続が成功する) をチェックする小さな c# クラスを作成しました。問題のエンドポイントが利用可能で、TCP セッションが実際に接続されている場合は、うまく機能しているように見えます。
ただし、エンドポイントがリッスンしておらず、接続がタイムアウトすると、奇妙なことが起こります。クラスは約 15 ~ 20 秒間「ハング」し続けます。これはデフォルトのタイムアウト値と一致します。
ただし、タイムアウトがトリガーされたときに socket.Close() を呼び出します。これは、MSDN ですべての非同期操作をキャンセルすると言われています。
接続が成功しない場合、クラスがアプリケーションのシャットダウンを防止するのはなぜですか? 私は何を間違っていますか?
public class CheckTCP
{
#region "Member Variables"
// socket connect timeout value
private int _timeout = 2000;
// check complete event
public event EventHandler<CheckCompletedEventArgs> CheckCompleted;
// perform TCP connect check
public void PerformCheck(EndPoint Socket)
{
StateObject state = new StateObject();
state.Me = this;
state.WorkSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
state.TimeoutTimer = new Timer();
state.TimeoutTimer.Interval = _timeout;
state.TimeoutTimer.Elapsed += (sender, e) => timeout_elapsed(sender, e, state);
state.TimeoutTimer.Start();
state.WorkSocket.SendTimeout = _timeout;
state.WorkSocket.ReceiveTimeout = _timeout;
state.WorkSocket.BeginConnect(Socket, new AsyncCallback(ConnectCallback), state);
}
// connection callback
private static void ConnectCallback(IAsyncResult ar)
{
StateObject state = (StateObject) ar.AsyncState;
state.TimeoutTimer.Stop();
state.TimeoutTimer.Dispose();
CheckCompletedEventArgs ea = new CheckCompletedEventArgs();
if (state.WorkSocket.Connected)
{
state.WorkSocket.EndConnect(ar);
state.WorkSocket.Close();
ea.Success = true;
state.Me.OnCheckCompleted(ea);
}
else
{
ea.Success = false;
state.Me.OnCheckCompleted(ea);
}
state.WorkSocket.Dispose();
state.Me = null;
}
// timeout callback
private void timeout_elapsed(object sender, EventArgs e, StateObject state)
{
state.TimeoutTimer.Stop();
state.WorkSocket.Close();
}
#endregion
// raiseevent helper
protected virtual void OnCheckCompleted(CheckCompletedEventArgs e)
{
// raise the event
EventHandler<CheckCompletedEventArgs> handler = CheckCompleted;
if (handler != null)
{
handler(this, e);
}
}
// checkcompleted event args class
public class CheckCompletedEventArgs : EventArgs
{
public bool Success { set; get; }
}
// async state object
public class StateObject
{
public EndPoint EndpointSocket { set; get; }
public Socket WorkSocket { set; get; }
public Timer TimeoutTimer { set; get; }
public CheckTCP Me { set; get; }
}
}