利用TcpClient快速得知對方主機是否活著

在.NET裡面某些網路連線元件在實作上缺乏Timeout設定的機制,這時候我們可以透過最底層的Socket來實作出類似Ping的動作,透過敲門來得知這部主機是否活著。當然,這時候的秒數我們就可以自行定義啦!

在這邊沒有特意去包成類別,請自行放在script runat="server",純粹展示概念,Browser端的物件不用說也知道是TextBox吧。大概動作就是我們不去調用TCPClient.GetStream指令了,因為這個動作還要包二進制陣列資料,而是改由直接下TCPClient.Connected,然後利用執行續去觀察它的處理結果。當然,所謂的Timeout時間,就是執行續的起來查看時間啦!

//定義TCP連線測試時間(千分之一秒)
public int iConnectTime = 1000;
//定義系統是否可以順利連線上
public bool bConnected = false;
//定義共用例外物件
public System.Exception oException = null;
//主要OnClick事件
protected void QueryTCPServer(object sender, EventArgs e)
{
  //利用Threading進行TCP敲門,如果TCP沒有回應的話(通常要20秒以上)且自己定義的時間到的話,就把整個執行緒停掉
  System.Threading.Thread oThread = new System.Threading.Thread(() => KnockDoor(targetIP.Text, 80));
  //設定執行緒背景運行
  oThread.IsBackground = true;
  //開始執行緒
  oThread.Start();
  //指定執行緒的逾時時間
  oThread.Join(iConnectTime);
  //如果執行緒內的KnockDoor在小於iConnectTime內運行完成,那他會自動把這個bConnected標記成true,並且結束執行緒。否則的話,執行緒就會在這邊卡住,直到Join(iConnectTime)到達,或者是KnockDoor運行完成,如果你的iConnectTime設定大於20秒,那你將會看到TCPException觸發錯誤。
  if (bConnected)
  {
    //主機活著
    showMe.Text = "主機活著";
    return;
  }
  if (oException != null)
  {
    //主機死掉(真的由TCP觸發連線逾時)
    oThread.Abort();
    showMe.Text = "主機死掉(TCP觸發連線逾時)";
    return;
  }
  else
  {
    //主機死掉(超過使用者自行定義時間)
    oThread.Abort();
    showMe.Text = "主機死掉(自行定義時間到達)";
    return;
  }
}
//TCP敲門副程式
public void KnockDoor(string cTempIP, int cTempPort)
{
  try
  { //由於TCP協定的限制,不可以設定連線時間,因此如果對方的FTP沒開,會卡在這一行卡很久
    using var oTcp = new System.Net.Sockets.TcpClient(cTempIP, cTempPort);
    //如果跑到這一行了,表示對方主機有開且連線已經成功,通常這樣的動作不到一秒就完成了。如果對方的主機沒開,那大約要等20秒才會跳到錯誤區塊
    bConnected = oTcp.Connected;
  }
  catch (System.Exception oEx)
  { //連線逾時
    oException = new System.Exception("TCP觸發連線逾時。");
  }
}

這裡巧妙的使用到Thread.Join來當作中斷的技巧,有興趣的人可以自己翻一下MSDN:https://msdn.microsoft.com/en-us/library/6b1kkss0%28v=vs.110%29.aspx

System.Net.Sockets.TcpClient System.Threading.Thread TCP Ping KnockDoor