UWP 模拟Ping 请求服务器状态

  笔者近期做的服务器监控UWP小程序,结果发现在UWP程序的.NET命名空间下取消了Ping的部分,看了诸多资料,觉得可能是.NET 4.5 Framework 暂时不支持ICMP。于是笔者想着通过Socket(命名空间保留了的部分)走上层模拟Ping请求,不过这种方式并不能完全达到效果,原因在于Socket建立连接是需要终结点的,即IP+端口号,而实际上ICMP请求是不需要端口号的,直接通过发送ICMP询问报文获取服务器状态即可。

  摘记笔者实现的简易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);
            }
        }

  上述实现方式中几个重要需要注意的点:

  • 方法体异步(async + await)
  • 异常捕获处理(可能还存在笔者未捕获到的异常)
  • 笔者代码中加入了人为超时判断,实际上使用DatagramSocket会自己有超时判断,大概是5s左右

  上面笔者是用的DatagramSocket实现的,实际上还有很多种Socket也可以实现:MessageWebSocketStreamSocket等等

OK,就先记录到这!

转载于:https://my.oschina.net/u/3744313/blog/1790493

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值