最近在实施MSN Direct项目时,需要用×××+ADSL方案把放在西格玛的服务器和电视塔上的发射设备连接在一起,为了测试网络是否正常,需要两边的人进行配合,通过Ping命令判断网络是否联通。由于电视塔仅周二下午才允许调试,调试时间有限,并且人手也有限,为了节省时间,所以萌生了做一个Windows Mobile Ping 命令的想法,这样通过手机就可以直接测试网络是否联通。

Windows Mobile是没有现成的Ping可用的,所以需要自己做一个。一种最直接的想法就是用Socket实现ICMP协议(针对PING命令的部分),对于桌面版的.Net Framework中的Socket,只要如下进行定义,就可以是实现收发ICMP数据包。

 

   
   
   
   
  1. Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp); 

但是很不幸的是.Net compact Framework不支持ProtocolType.Icmp参数,所以也无从用Socket实现了。幸好天无绝人之路,Windows Mobile还提供了Icmp的API接口,可以通过这些API接口,实现PING命令的功能,核心代码如下:

   
   
   
   
  1. public class Sw  
  2.  
  3. {  
  4.  
  5.     #region P/Invoke  
  6.  
  7.     [DllImport("\\windows\\iphlpapi.dll", SetLastError = true)]  
  8.  
  9.     static extern IntPtr IcmpCreateFile();  
  10.  
  11.     [DllImport("\\windows\\iphlpapi.dll", SetLastError = true)]  
  12.  
  13.     static extern bool IcmpCloseHandle(IntPtr handle);  
  14.  
  15.     [DllImport("\\windows\\iphlpapi.dll", SetLastError = true)]  
  16.  
  17.     static extern Int32 IcmpSendEcho(IntPtr icmpHandle, Int32 destinationAddress, String requestData, Int16 requestSize, ref IP_OPTION_INFORMATION requestOptions, ref ICMP_ECHO_REPLY replyBuffer, Int32 replySize, Int32 timeout);  
  18.  
  19.     [StructLayout(LayoutKind.Sequential)]  
  20.  
  21.     public struct IP_OPTION_INFORMATION  
  22.  
  23.     {  
  24.  
  25.         public byte TTL;  
  26.  
  27.         public byte TOS;  
  28.  
  29.         public byte Flags;  
  30.  
  31.         public byte OptionsSize;  
  32.  
  33.         public IntPtr OptionsData;  
  34.  
  35.     }  
  36.  
  37.         
  38.  
  39.     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]  
  40.  
  41.     private struct ICMP_ECHO_REPLY  
  42.  
  43.     {  
  44.  
  45.         public int Address;  
  46.  
  47.         public int Status;  
  48.  
  49.         public int RoundTripTime;  
  50.  
  51.         public Int16 DataSize;  
  52.  
  53.         public Int16 Reserved;  
  54.  
  55.         public IntPtr DataPtr;  
  56.  
  57.         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 250)]  
  58.  
  59.         public String Data;  
  60.  
  61.         public IP_OPTION_INFORMATION Options;  
  62.  
  63.     }  
  64.  
  65.     #endregion  
  66.  
  67.     public static int ping(string ip, int timeout,out string info)  
  68.  
  69.     {  
  70.  
  71.         IPEndPoint host = new IPEndPoint(Dns.GetHostEntry(ip).AddressList[0], 0);  
  72.  
  73.         if (host == null | Environment.OSVersion.Platform != PlatformID.WinCE)  
  74.  
  75.         {  
  76.  
  77.             info = "ip error!";  
  78.  
  79.             return -1;  
  80.  
  81.         }          
  82.  
  83.         int result = -1;  
  84.  
  85.         IntPtr ICMPHandle;  
  86.  
  87.         Int32 iIP;  
  88.  
  89.         String sData;  
  90.  
  91.         IP_OPTION_INFORMATION oICMPOptions = new IP_OPTION_INFORMATION();  
  92.  
  93.         ICMP_ECHO_REPLY ICMPReply = new ICMP_ECHO_REPLY();  
  94.  
  95.         Int32 iReplies;  
  96.  
  97.         ICMPHandle = IcmpCreateFile();  
  98.  
  99.         iIP = BitConverter.ToInt32(host.Address.GetAddressBytes(), 0);  
  100.  
  101.         sData = "abcdefghijklmnopqrstuvwxyz012345";  
  102.  
  103.         oICMPOptions.TTL = 255;  
  104.  
  105.         iReplies = IcmpSendEcho(ICMPHandle, iIP, sData, (Int16)sData.Length, ref oICMPOptions, ref ICMPReply, Marshal.SizeOf(ICMPReply), timeout);  
  106.  
  107.         if (ICMPReply.Status == 0)  
  108.  
  109.         {  
  110.  
  111.             result = ICMPReply.RoundTripTime;  
  112.  
  113.             info = "ping bytes=" + sData.Length.ToString() + " time=" + result.ToString() + "ms TTL=" + oICMPOptions.TTL.ToString();  
  114.  
  115.         }  
  116.  
  117.         else 
  118.  
  119.         {  
  120.  
  121.             info = "ping " + ip + " timed out.";  
  122.  
  123.         }  
  124.  
  125.         IcmpCloseHandle(ICMPHandle);              
  126.  
  127.         return result;  
  128.  
  129.     }  
  130.  
  131. }  
  132.  

最终程序运行后的界面如下:

 

Windows Mobile Ping 命令实现_第1张图片


需要注意的是,GPRS连接必须是CMNET(关于如何建立GPRS连接,有兴趣的朋友可以参考我以前写的文章:让智能手机和居家电脑互联互通(WM6 GPRS)),否则是无法PING通公网IP的,此外我们发现Windows Mobile手机的IP为10.x.x.x,我们知道10开头的IP地址是A类地址,查相关资料,我们可知10.0.0.0到10.255.255.255是私有地址(所谓的私有地址就是在互联网上不使用,而被用在局域网络中的地址)。每个A类地址理论上可连接16777214台主机,这大约是1千六百万台,这也是同时使用GPRS的手机数上限了。由于Windows Mobile手机分配的IP地址不是公网IP,所以很遗憾,我们不能在PC上Ping  Windows Mobile手机,也就无法测试PC的Ping出命令是否正常了。[叶帆工作室]