.NET Compact Framework下的Ping(ICMP)的开发

简介:

什么是 Ping Tester?

Ping Tester是一个网络侦测工具(Diagnostics),可以使用在Windows Mobile来检查网络的联通性。

 

简介

文本讲述了在.NET Compact Framework下ping功能的实现。 主要通过P/Invoke的方式调用ICMP相关的API来实现。 同时提供一个Windows Mobile的工具来调用Ping封装类。

 

背景

由于在3G网络下开发数据通信程序,需要验证该网络的连通性和可靠性,所以开发这个Ping封装类方便验证网络的可靠性。

 

原理

Ping(Packet InterNet Groper)是一个网络诊断工具,他的工作原理就是 发送ICMP的“echo request” 数据包到目标主机,然后监听ICMP的“echo response”回应数据包。 Ping通过度量反应时间(round-trip time, RTT)和记录所有丢包情况等信息,产生一个统计报告。下面是我电脑ping博客园的例子,请大家看看本人的网络是如何的不可靠,生活在水深火热的中,写Blog常常断网。


复制代码
C:\ > ping cnblogs.com

Pinging cnblogs.com [
222.92 . 117.56 ] with  32  bytes of data:

Request timed 
out .
Request timed 
out .
Reply from 
222.92 . 117.56 : bytes = 32  time = 360ms TTL = 108
Reply from 
222.92 . 117.56 : bytes = 32  time = 359ms TTL = 108

Ping statistics 
for   222.92 . 117.56 :
    Packets: Sent 
=   4 , Received  =   2 , Lost  =   2  ( 50 %  loss),
Approximate round trip times 
in  milli - seconds:
    Minimum 
=  359ms, Maximum  =  360ms, Average  =  359ms 
复制代码

ping的详细介绍可以参考这篇文章 http://en.wikipedia.org/wiki/Ping

 

解决方案

从上述的原理可知,对ping的开发其实就是对ICMP协议的开发。Internet Control Message Protocol (ICMP) 是网络层的协议,其负责网络主机之间的控制流信息,错误消息,路由信息以及其他数据的传输。关于 ICMP的详细介绍 可以参考这篇文章Internet Control Message Protocol (ICMP)

进行ICMP的开发,主要有以下几个API:
IcmpCreateFile     生成发送ICMP请求的句柄。
IcmpSendEcho2   发送ICMP请求,并得到回应信息。
IcmpCloseHandle  关闭IcmpCreateFile生成的句柄。

下面为这些API的P/Invoke

复制代码
[DllImport( " iphlpapi.dll " )]
internal   static   extern  IntPtr IcmpCreateFile();

[DllImport(
" iphlpapi.dll " )]
internal   static   extern   uint  IcmpSendEcho2(IntPtr icmpHandle, IntPtr Event, IntPtr apcRoutine, IntPtr apcContext,  uint  ipAddress, IntPtr data,  ushort  dataSize,  ref  IPOptions options, IntPtr replyBuffer,  uint  replySize,  uint  timeout);

[DllImport(
" iphlpapi " )]
internal   static   extern   bool  IcmpCloseHandle(IntPtr handle); 
复制代码


通过参考Smart Device Framework 1.4源代码,我实现了一个Ping的封装类, Smart Device Framework 1.4可以在下面链接下载 http://www.opennetcf.com/Products/SmartDeviceFramework/tabid/65/Default.aspx

复制代码
public  IcmpEchoReply Send(IPAddress address,  int  timeout)
{
    
if  (handle  ==  IntPtr.Zero)
    {
        handle 
=  IcmpCreateFile();
    } 

    
if  (replyBuffer  ==  IntPtr.Zero)
    {
        replyBuffer 
=  LocalAlloc(LPTR, ( uint ) 0xffff );
    } 

    requestBuffer 
=  LocalAlloc(LPTR, ( uint )SendBuffer.Length);
    Marshal.Copy(SendBuffer, 
0 , requestBuffer, SendBuffer.Length); 

    
uint  ip  =  BitConverter.ToUInt32(address.GetAddressBytes(),  0 ); 

    IPOptions option 
=   new  IPOptions( null   as  PingOptions); 

    IcmpSendEcho2(handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ip, requestBuffer, (
ushort )SendBuffer.Length,  ref  option, replyBuffer,  0xffff , ( uint )timeout);
    
if  (requestBuffer  !=  IntPtr.Zero)
    {
        LocalFree(requestBuffer);
        requestBuffer 
=  IntPtr.Zero;
    }
    
return  Marshal.PtrToStructure(replyBuffer,  typeof (IcmpEchoReply))  as  IcmpEchoReply;
}

复制代码

上面是发送ICMP请求的核心代码,代码的逻辑是 先生成一个ICMP句柄,为返回结果包分配内存,对发送包进行赋值。然后发送ICMP请求,并等待回应。当接收到回应时把回应的数据包赋值到IcmpEchoReply结构体里面。回应信息可以通过IcmpEchoReply结构体取出。IcmpEchoReply信息可参考下面的客户端代码。

 

客户端

复制代码
IcmpEchoReply reply  =  ping.Send(ip);
if  (reply.status  ==  ( uint )IPStatus.Success)
{
    IPAddress addr 
=   new  IPAddress(reply.address);
    ShowMessage(String.Format(
" Reply from {0}: Echo size={1} time<{2}ms TTL={3} " , addr, reply.dataSize, reply.roundTripTime, reply.ttl));
}
else
{
    IPStatus ipStatus 
=  (IPStatus)reply.status;
    ShowMessage(String.Format(
" PING: transmit failed, error code {0}, {1} " , reply.status.ToString(), ipStatus));
}
复制代码

客户端调用的时候只需要调用Send()方法,然后分析IcmpEchoReply的结果。

ping1 
图1

为了提高可用性,增加对域名的支持。

复制代码
IPAddress address  =   null ;
IPAddress[] addressList 
=   null ;
try
{
    address 
=  IPAddress.Parse(uri);
}
catch
{
    
try
    {
        IPHostEntry entry 
=  Dns.GetHostEntry(uri);
        addressList 
=  entry.AddressList;
    }
    
catch  (Exception ex)
    {
        ShowMessage(String.Format(
" Ping request could not find host {0}. Please check the name and try again. {1} " , textBoxAddress.Text, ex.Message));
    }


if  (address  !=   null )
{
    ShowMessage(String.Format(
" Pinging Host {0} " , uri));
    Ping(address);
}
else
{
    
for  ( int  i  =   0 ; i  <  addressList.Length;  ++ i)
    {
        ShowMessage(String.Format(
" Pinging Host {0} [{1}] " , uri, addressList[i]));
        Ping(addressList[i]);
    }
}

复制代码

当用户输入不是IP地址的时候,会对域名进行解释,把该域名的所对应的所有IP解释出来,存放到addressList里面,然后对每个IP进行Ping。
下面为ping www.google.com的例子,http://www.google.com/对应3个不同的IP。

ping2 
图2


源代码:PingTester.rar

运行环境:VS2008 + Windows Mobile 6 Professional SDK  + CF.NET 2.0

 


    本文转自Jake Lin博客园博客,原文链接:http://www.cnblogs.com/procoder/archive/2009/06/19/1506823.html,如需转载请自行联系原作者



相关文章
|
1月前
|
SQL 开发框架 数据可视化
企业应用开发中.NET EF常用哪种模式?
企业应用开发中.NET EF常用哪种模式?
|
2月前
|
开发框架 JavaScript 前端开发
5个.NET开源且强大的快速开发框架(帮助你提高生产效率)
5个.NET开源且强大的快速开发框架(帮助你提高生产效率)
|
4月前
|
SQL 开发框架 数据可视化
企业应用开发中.NET EF常用哪种模式?
企业应用开发中.NET EF常用哪种模式?
|
11天前
|
开发框架 前端开发 JavaScript
采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示
技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
1月前
|
数据安全/隐私保护 Windows
.net三层架构开发步骤
.net三层架构开发步骤
13 0
|
1月前
深入.net平台的分层开发
深入.net平台的分层开发
62 0
|
1月前
|
Windows
windows server 2019 安装NET Framework 3.5失败,提示:“安装一个或多个角色、角色服务或功能失败” 解决方案
windows server 2019 安装NET Framework 3.5失败,提示:“安装一个或多个角色、角色服务或功能失败” 解决方案
140 0
|
2月前
|
开发框架 前端开发 .NET
福利来袭,.NET Core开发5大案例,30w字PDF文档大放送!!!
为了便于大家查找,特将之前开发的.Net Core相关的五大案例整理成文,共计440页,32w字,免费提供给大家,文章底部有PDF下载链接。
35 1
福利来袭,.NET Core开发5大案例,30w字PDF文档大放送!!!
|
3月前
|
C#
.NET开发中合理使用对象映射库,简化和提高工作效率
.NET开发中合理使用对象映射库,简化和提高工作效率
|
3月前
|
开发框架 前端开发 JavaScript
一款基于.NET Core的快速开发框架、支持多种前端UI、内置代码生成器
一款基于.NET Core的快速开发框架、支持多种前端UI、内置代码生成器
100 0