[.NET Code] 如何在指定的逾時時間內偵測伺服器能否連接

問題

應用程式使用 .NET WebClient 類別執行偵測新版本以及線上自動更新的功能,可是如果伺服器因為某些原因無法連線(如網路斷線、伺服器關機等),應用程式在檢查是否有更新版時,就得等 20 秒左右才會發生連線失敗。
想要使用 Socket 或 TcpClient 類別事先偵測伺服器的 80 port 能否連線,可是結果還是一樣,因為它們並沒有提供連線逾時的屬性。

解決方法

可使用非同步的方式解決。以下是利用 TcpClient 類別偵測伺服器 80 port 能否連接的工具函式:

/// <summary>

/// 偵測指定的伺服器的特定 port 是否可以連接。

/// </summary>

/// <param name="host">伺服器名稱或 IP 位址。</param>

/// <param name="port">Port 號。</param>

/// <param name="timeOut">連線逾時時間,單位:秒。</param>

/// <returns></returns>

private bool IsServerConnectable(string host, int port, double timeOut)

{

  TcpClient tcp = new TcpClient();

  DateTime t = DateTime.Now;

 

  try

  {

    IAsyncResult ar = tcp.BeginConnect(host, port, null, null);

    while (!ar.IsCompleted)

    {

      if (DateTime.Now > t.AddSeconds(timeOut))

      {

        throw new Exception("Connection timeout!");

      }

      System.Threading.Thread.Sleep(100);

    }

 

    tcp.EndConnect(ar);

    tcp.Close();

    return true;

  }

  catch

  {

    return false;

  }

}


呼叫 IsServerConnectable 時,可將參數 timeOutSeconds 指定為 1,如此一來,函式最多只等待 1 秒便會立即傳回結果。

2008-11-22 增加:偵測某個網頁是否能正常回應

    private void PingWebPage(string url, int timeout)

    {

      HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url);

      req.Method = "GET";

      req.Credentials = CredentialCache.DefaultCredentials;

      req.ContentType = "text/xml";

      req.Timeout = timeout;

      WebResponse rsp = req.GetResponse();

      StreamReader sr = new StreamReader(rsp.GetResponseStream(), Encoding.UTF8);

      try

      {

        sr.ReadLine();

      }

      finally

      {

        sr.Close();

        rsp.Close();       

      }

    }


p.s. 以上程式碼是由 CopySourceAsHtml 產生。選項:Wrap words + Embed styles + Overwrite tab size + Overwrite font list (Fixedsys) + Strip line breaks。

沒有留言:

技術提供:Blogger.
回頂端⬆️