用Delphi实现智能化Ping命令功能

用Delphi实现智能化Ping命令功能

2007-11-08 14:21

《软件报》28期

众所周知,Ping命令是Windows系统自带的一个针对TCP/IP协议的可执行命令,其主要作用是通过发送数据包并接收应答信息来检测两台计算机之间的网络是否连通。当网络出现故障时,可以用这个命令来检测故障和确定故障地点。但在MS-DOS方式下执行此命令,而且每秒钟执行一次Ping操作,显得似乎有些另类,今天,我们将实现智能化Ping命令的功能,并实现操作的可视化。

一、系统Ping命令的功能与执行

命令执行格式:Ping IP地址 参数

其中,参数最常用的就是-t,用于不间断Ping操作。在执行Ping的过程中,可以使用Pause键暂停,也可以使用Ctrl+Pause组合键显示截至当前时刻Ping操作的总次数、掉包次数以及掉包率,从而判断网络的稳定性。Ping命令执行结果返回字节数(bytes)、执行时间(time)、生存时间(TTL)等信息。

二、编程原理

Ping命令是属于ICMP协议规定的,而ICMP是内嵌于IP层的,因此, Ping是属于网络层的命令。Ping的实现过程很简单,命令将引发IP层发送一个简单的IP包,而目的方收到这个包之后,将源和目的地址做一下交换,重新发出这个包即可。简单来说,为了避免数据包在网路上的传送路径造成死循环或者无休止的投递下去,每个IP数据包都包含一个寿命计数器,这个就是数据包的的生存时间TTL,只要一个路由器处理过这个数据包,它就递减这个数据包的寿命计数,当寿命计数递减到0的时候,路由器就丢弃该包,TTL在一定程度上反应了一个IP数据包经过的路由器的多少。

三、编程实现

在Delphi中,我们可以使用IdIcmpClient组件(位 于Indy Client选项卡中)实现Ping操作。添加此组件到窗体,再添加一个文本框控件edtHost(输入IP)、一个列表框控件Info(显示信息)、两个命令按钮btnPing(执行Ping命令)、btnStop(停止Ping命令)。设置IdIcmpClient控件的名称为ICMP、 ReceiveTimeout属性(超时)值为1000、OnReply事件为ICMPReply。合理布局,然后编写程序代码:

Var i,b,s:integer; //全局变量

1、执行Ping操作

通过ICMP控件的Host属性设置Ping的IP,然后调用控件的Ping方法执行Ping操作命令。核心代码如下:

Procedure TfrmPing.btnPingClick(…);

begin

b:=0; //掉包数量

i:=0; //Ping的总次数

s:=0; //执行(s=0)或停止(s=1)标志

Info.Clear; //清除上次Ping的信息

ICMP.Host:=edtHost.Text; //置IP

While (i<100000) and (s=0) Do

begin //最多执行10万次Ping操作

Application.ProcessMessages;

i:=i+1; ICMP.Ping; //执行Ping

//若前10次Ping都失败则结束Ping

if (i=10) and (b=10) then s:=1;

end;

end;

//停止Ping操作

procedure TfrmPing.btnStopClick(…);

begin

s:=1; //置Ping操作停止标志

end;

2、返回Ping命令的执行结果

在ICMP控件的ICMPReply事件中,根据ReplyStatus对象的返回值确定Ping操作的执行情况,并返回相应的信息,ReplyStatus对象的部分属性如下:

TimeToLive:返回生存时间(TTL)。如果返回值为0,则认为Ping操作失败,可判断为网络故障或掉包。

BytesReceived:返回的字节数。如果返回值为0,也有可能为网络故障或掉包。

MsRoundTripTime:返回执行时间。需要说明的是,返回时间是以ms为单位的整数值,如果执行时间<1ms,则返回值为0,这种情况的执行时间程序按1ms计算。核心代码如下:

procedure TfrmPing.ICMPReply(ASender:TComponent;const ReplyStatus:TReplyStatus);

var Msg:string;Tm:integer;

begin

With ReplyStatus do

begin

Msg:=’Reply from ’+edtHost.Text;

Msg:=Msg+’ bytes=’+IntToStr(BytesReceived); //返回字节数

Msg:=Msg+’ TTL=’+IntToStr(TimeToLive); //返回生存时间

Tm:=MsRoundTripTime; //返回执行时间

if Tm<1 then Tm:=1;

Msg:=Msg+’ time=’+IntToStr(Tm)+’ms’;

Info.Items.Add(msg); //保存信息

if (BytesReceived=0) or (TimeToLive=0) then

begin //无数据返回

b:=b+1; //记录掉包数量

info.ItemIndex:=info.Items.Count-1;

end;

if i mod 100 =0 then panel1.Caption:=’Lost:’+IntToStr(b)+’/’+IntToStr(i)+’=’+copy (FloatToStr(b/i*1000),1,4)+’‰’; //每Ping到100次显示一次掉包情况

end;

end;

四、小结

本文调用Delphi提供的组件实现了Ping命令的智能化和可视化操作,同时能实时显示掉包情况,能有效地反应本机到目的IP之间网络的稳定性(与两端之间的路由器数量及其性能密切相关)。下图是测试笔者客户端与本地电信服务器之间的网络稳定性的运行结果,调试环境:WinXp+Delphi7。