c# ping

c# ping
2007年10月27日 星期六 19:29

icscs
本文主要是用于熟悉.NET 2.0中一个新的命名空间System.Net.NetworkInformation的使用,这个命名空间包括了一个Ping类...

翻译

Stefan Prodan著Ping.exe replica in C# 2.0

简介


我正在做一个应用程序,它需要连接到一个webservice并和它交换数据。因此在创建proxy对象之前,我需要检查这个客户端是否已经连接到inernet,是否能够访问到Webservice的网络地址。最容易的方法是使用Process类直接调用Ping.exe应用程序,然后获取我需要的信息。但是,为了这么小的一个功能就去调用一个外部应用程序是很不好代码,更不用说还有调用系统组件的安全性问题。在 .NET Framework 1.0 或 1.1中,微软并没有提供一个类似ping功能的类。不过,在搜索了MSDN之后,我发现在C#2.0中,有一个新的命名空间System.Net.NetworkInformation,这个命名空间包括了一个Ping类。

因此,我写了一个仅仅包含170行代码的控制台应用程序熟悉这个类的使用。

背景


MSDN 对System.Net.NetworkInformation.Ping 类的描述 http://msdn2.microsoft.com/en-us/library/system.net.networkinformation.ping.aspx
Wesley Brown在CodeProject上发表的C# 1.1 Ping Component
http://www.codeproject.com/dotnet/CSharpPing.asp

参考本站的译文C#实现ping功能(.net 1.1)

代码使用

这个应用程序的Main方法非常简单;它需要一个地址,然后调用DNS.GetHostEntry方法处理这个地址。不过在处理之前,调用了IsOffline方法,用以判断客户端是否连接到因特网。IsOffline方法使用系统链接库Winnet中的InternetGetConnectedState方法。


检查因特网连接

[Flags]
enum ConnectionState : int
{
       INTERNET_CONNECTION_MODEM = 0x1,
       INTERNET_CONNECTION_LAN = 0x2,
       INTERNET_CONNECTION_PROXY = 0x4,
       INTERNET_RAS_INSTALLED = 0x10,
       INTERNET_CONNECTION_OFFLINE = 0x20,
       INTERNET_CONNECTION_CONFIGURED = 0x40
}

[DllImport("wininet", CharSet = CharSet.Auto)]
static extern bool InternetGetConnectedState(ref ConnectionState lpdwFlags, 
                                             int dwReserved);

static bool IsOffline()
{
       ConnectionState state = 0;
       InternetGetConnectedState(ref state, 0);
    if (((int)ConnectionState.INTERNET_CONNECTION_OFFLINE & (int)state) != 0)
       {
        return true;
       }

    return false;
}

 

在一个StartPing方法的线程中执行ping

static void StartPing(object argument)
{
       IPAddress ip = (IPAddress)argument;

      //set options ttl=128 and no fragmentation
       PingOptions options = new PingOptions(128, true);

      //创建一个Ping对象
       Ping ping = new Ping();

      //32个空字节的缓冲区
       byte[] data = new byte[32];

      int received = 0;
       List<long> responseTimes = new List<long>();

      //ping 4 次
      for (int i = 0; i < 4; i++)
       {
           PingReply reply = ping.Send(ip, 1000, data, options);

          if (reply != null)
           {
              switch (reply.Status)
               {
                  case IPStatus.Success:
                       Console.WriteLine("Reply from {0}: " +
                          "bytes={1} time={2}ms TTL={3}",
                           reply.Address, reply.Buffer.Length,
                           reply.RoundtripTime, reply.Options.Ttl);
                       received++;
                       responseTimes.Add(reply.RoundtripTime);
                      break;
                  case IPStatus.TimedOut:
                       Console.WriteLine("Request timed out.");
                      break;
                  default:
                       Console.WriteLine("Ping failed {0}",
                                         reply.Status.ToString());
                      break;
               }
           }
          else
           {
               Console.WriteLine("Ping failed for an unknown reason");
           }
       }

      //统计信息
      long averageTime = -1;
      long minimumTime = 0;
      long maximumTime = 0;

      for (int i = 0; i < responseTimes.Count; i++)
       {
          if (i == 0)
           {
               minimumTime = responseTimes[i];
               maximumTime = responseTimes[i];
           }
          else
           {
              if (responseTimes[i] > maximumTime)
               {
                   maximumTime = responseTimes[i];
               }
              if (responseTimes[i] < minimumTime)
               {
                   minimumTime = responseTimes[i];
               }
           }
           averageTime += responseTimes[i];
       }

       StringBuilder statistics = new StringBuilder();
       statistics.AppendFormat("Ping statistics for {0}:", ip.ToString());
       statistics.AppendLine();
       statistics.AppendFormat("      Packets: Sent = 4, " +
          "Received = {0}, Lost = {1} <{2}% loss>,",
           received, 4 - received, Convert.ToInt32(((4 - received) * 100) / 4));
       statistics.AppendLine();
       statistics.Append("Approximate round trip times in milli-seconds:");
       statistics.AppendLine();

      //在loss不为100%时显示
      if (averageTime != -1)
       {
           statistics.AppendFormat("       Minimum = {0}ms, " +
              "Maximum = {1}ms, Average = {2}ms",
               minimumTime, maximumTime, (long)(averageTime / received));
       }

       Console.WriteLine();
       Console.WriteLine(statistics.ToString());
       Console.WriteLine();
       Console.WriteLine("Press any key to exit.");
       Console.ReadLine();
}


Main函数首先检查用户是否输入了一个IP,然后验证是否连接到因特网,转换到IPAddress 类型,并开始线程。

static void Main(string[] args)
{
       string address = string.Empty;

      if (args.Length == 0)
       {
           Console.WriteLine("PingDotNet needs a host or IP address, insert one");
           address = Console.ReadLine();
           Console.WriteLine();
       }
      else
       {
           address = args[0];
       }

      if (IsOffline())
       {
           Console.WriteLine("No internet connection detected.");
           Console.WriteLine("Press any key to exit.");
           Console.ReadLine();
          return;
       }

       IPAddress ip = null;
      try
       {
           ip = Dns.GetHostEntry(address).AddressList[0];
       }
      catch (System.Net.Sockets.SocketException ex)
       {
           Console.WriteLine("DNS Error: {0}", ex.Message);
           Console.WriteLine("Press any key to exit.");
           Console.ReadLine();
          return;
       }

       Console.WriteLine("Pinging {0} [{1}] with 32 bytes of data:",
                         address, ip.ToString());
       Console.WriteLine();
       Thread pingThread = new Thread(new ParameterizedThreadStart(StartPing));
       pingThread.Start(ip);
       pingThread.Join();
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值