筆者近期作的服務器監控UWP小程序,結果發如今UWP程序的.NET命名空間下取消了Ping的部分,看了諸多資料,以爲多是.NET 4.5 Framework 暫時不支持ICMP。因而筆者想着經過Socket(命名空間保留了的部分)走上層模擬Ping請求,不過這種方式並不能徹底達到效果,緣由在於Socket創建鏈接是須要終結點的,即IP+端口號,而實際上ICMP請求是不須要端口號的,直接經過發送ICMP詢問報文獲取服務器狀態便可。web
摘記筆者實現的簡易Ping方法:小程序
/// <summary> /// 以數據報的消息格式請求鏈接服務器 /// </summary> /// <param name="desEndPoing">終結點</param> /// <returns></returns> public static async Task<Tuple<string, string, string, string>> DatagramSocketConnect(IPEndPoint desEndPoing) { // 請求狀態 string requestStatus = ""; // 請求耗時 string requestCost = ""; // 請求結果 string color = ""; // 請求的額外信息 string others = ""; // 用來記錄請求耗時 var s = new System.Diagnostics.Stopwatch(); s.Start(); try { // 使用數據報進行消息傳輸 using (var UdpClient = new DatagramSocket()) { // 超時控制 CancellationTokenSource cts = new CancellationTokenSource(); cts.CancelAfter(1000); // HostName 構造須要一個主機名orIP地址(不帶http!) // 異步創建鏈接 await UdpClient.ConnectAsync( new Windows.Networking.HostName(desEndPoing.Address.ToString()), desEndPoing.Port.ToString()) // 做爲Task任務,添加超時令牌 .AsTask(cts.Token); // 停表 s.Stop(); var remoteIp = UdpClient.Information.RemoteAddress; Debug.WriteLine(String.Format("Success, remote server contacted at IP address {0},and the connecting work cost {1} millsseconds!", remoteIp, s.ElapsedMilliseconds)); #region 修改返回數據 requestStatus = "200"; requestCost = s.ElapsedMilliseconds.ToString(); color = "green"; others = String.Format("Success, remote server contacted at IP address {0},and the connecting work cost {1} millsseconds!", remoteIp, s.ElapsedMilliseconds); #endregion // 釋放鏈接 UdpClient.Dispose(); return new Tuple<string, string, string, string>(requestStatus, requestCost, color, others); } } // 捕獲自定義超時異常 catch (TaskCanceledException) { #region 修改返回數據 requestStatus = "1000"; requestCost = s.ElapsedMilliseconds.ToString(); color = "orange"; others = "Error: Timeout when connecting (check hostname and port)"; #endregion return new Tuple<string, string, string, string>(requestStatus, requestCost, color, others); } // 捕獲常見的異常 catch (Exception ex) { s.Stop(); // 查不到對應HostName的服務器 if (ex.HResult == -2147013895) { #region 修改返回數據 requestStatus = "0"; requestCost = s.ElapsedMilliseconds.ToString(); color = "red"; others = "Error: No such host is known"; #endregion Debug.WriteLine("Error: No such host is known"); } // 請求超時 else if (ex.HResult == -2147014836) { #region 修改返回數據 requestStatus = "1000"; requestCost = s.ElapsedMilliseconds.ToString(); color = "orange"; others = "Error: Timeout when connecting (check hostname and port)"; #endregion Debug.WriteLine("Error: Timeout when connecting (check hostname and port)"); } // 其餘異常 else { #region 修改返回數據 requestStatus = "0"; requestCost = s.ElapsedMilliseconds.ToString(); color = "red"; others = "Error: Exception returned from network stack: " + ex.Message; #endregion Debug.WriteLine("Error: Exception returned from network stack: " + ex.Message); } return new Tuple<string, string, string, string>(requestStatus, requestCost, color, others); } }
上述實現方式中幾個重要須要注意的點:windows
上面筆者是用的DatagramSocket實現的,實際上還有不少種Socket也能夠實現:MessageWebSocket、StreamSocket等等api
OK,就先記錄到這!服務器