最近在实施MSN Direct项目时,需要用VPN+ADSL方案把放在西格玛的服务器和电视塔上的发射设备连接在一起,为了测试网络是否正常,需要两边的人进行配合,通过Ping命令判断网络是否联通。由于电视塔仅周二下午才允许调试,调试时间有限,并且人手也有限,为了节省时间,所以萌生了做一个Windows Mobile Ping 命令的想法,这样通过手机就可以直接测试网络是否联通。
Windows Mobile是没有现成的Ping可用的,所以需要自己做一个。一种最直接的想法就是用Socket实现ICMP协议(针对PING命令的部分),对于桌面版的.Net Framework中的Socket,只要如下进行定义,就可以是实现收发ICMP数据包。
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
但是很不幸的是.Net compact Framework不支持ProtocolType.Icmp参数,所以也无从用Socket实现了。幸好天无绝人之路,Windows Mobile还提供了Icmp的API接口,可以通过这些API接口,实现PING命令的功能,核心代码如下:
public class Sw
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
P/Invoke#region P/Invoke
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[DllImport("\\windows\\iphlpapi.dll", SetLastError = true)]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
static extern IntPtr IcmpCreateFile();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[DllImport("\\windows\\iphlpapi.dll", SetLastError = true)]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
static extern bool IcmpCloseHandle(IntPtr handle);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[DllImport("\\windows\\iphlpapi.dll", SetLastError = true)]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[StructLayout(LayoutKind.Sequential)]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public struct IP_OPTION_INFORMATION
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public byte TTL;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public byte TOS;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public byte Flags;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public byte OptionsSize;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public IntPtr OptionsData;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private struct ICMP_ECHO_REPLY
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public int Address;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public int Status;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public int RoundTripTime;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public Int16 DataSize;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public Int16 Reserved;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public IntPtr DataPtr;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 250)]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public String Data;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public IP_OPTION_INFORMATION Options;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public static int ping(string ip, int timeout,out string info)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IPEndPoint host = new IPEndPoint(Dns.GetHostEntry(ip).AddressList[0], 0);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (host == null | Environment.OSVersion.Platform != PlatformID.WinCE)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
info = "ip error!";
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
return -1;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
int result = -1;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IntPtr ICMPHandle;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Int32 iIP;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
String sData;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IP_OPTION_INFORMATION oICMPOptions = new IP_OPTION_INFORMATION();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
ICMP_ECHO_REPLY ICMPReply = new ICMP_ECHO_REPLY();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Int32 iReplies;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
ICMPHandle = IcmpCreateFile();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
iIP = BitConverter.ToInt32(host.Address.GetAddressBytes(), 0);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
sData = "abcdefghijklmnopqrstuvwxyz012345";
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
oICMPOptions.TTL = 255;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
iReplies = IcmpSendEcho(ICMPHandle, iIP, sData, (Int16)sData.Length, ref oICMPOptions, ref ICMPReply, Marshal.SizeOf(ICMPReply), timeout);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (ICMPReply.Status == 0)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
result = ICMPReply.RoundTripTime;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
info = "ping bytes=" + sData.Length.ToString() + " time=" + result.ToString() + "ms TTL=" + oICMPOptions.TTL.ToString();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
else
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
info = "ping " + ip + " timed out.";
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IcmpCloseHandle(ICMPHandle);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
return result;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
最终程序运行后的界面如下:
![](https://images.cnblogs.com/cnblogs_com/greatandforever/WMPing09092101.jpg)
需要注意的是,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出命令是否正常了。[叶帆工作室]
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yefanqiu/archive/2009/09/21/4578180.aspx