Cハハソケット接続要求タイムアウト機構によるコード共有の実現


ネットのSystem.Net.Sockets.TcpClientとSystem.Net.Sockets.Socketは直接にConnect/BeginnConnectにタイムアウト制御機構を提供していません。したがって、サーバが傍受状態になっていない、またはネットワーク障害が発生した場合、クライアント接続要求は、異常が発生するまで、長い間待たされる。デフォルトの待ち時間は20~30 sです。Net SocketライブラリのSocketOption Name.SendTimeoutは、送信データを制御するタイムアウト時間を提供しているが、ここで論じた接続要求のタイムアウト時間ではない。以下を実現することは、実現されるキーコードである。

class TimeOutSocket
{
    private static bool IsConnectionSuccessful = false;
    private static Exception socketexception;
    private static ManualResetEvent TimeoutObject = new ManualResetEvent(false);

    public static TcpClient TryConnect(IPEndPoint remoteEndPoint, int timeoutMiliSecond)
    {
        TimeoutObject.Reset();
        socketexception = null; 

        string serverip = Convert.ToString(remoteEndPoint.Address);
        int serverport = remoteEndPoint.Port;          
        TcpClient tcpclient = new TcpClient();

        tcpclient.BeginConnect(serverip, serverport,
            new AsyncCallback(CallBackMethod), tcpclient);

        if (TimeoutObject.WaitOne(timeoutMiliSecond, false))
        {
            if (IsConnectionSuccessful)
            {
                return tcpclient;
            }
            else
            {
                throw socketexception;
            }
        }
        else
        {
            tcpclient.Close();
            throw new TimeoutException("TimeOut Exception");
        }
    }
    private static void CallBackMethod(IAsyncResult asyncresult)
    {
        try
        {
            IsConnectionSuccessful = false;
            TcpClient tcpclient = asyncresult.AsyncState as TcpClient;

            if (tcpclient.Client != null)
            {
                tcpclient.EndConnect(asyncresult);
                IsConnectionSuccessful = true;
            }
        }
        catch (Exception ex)
        {
            IsConnectionSuccessful = false;
            socketexception = ex;
        }
        finally
        {
            TimeoutObject.Set();
        }
    }
}