眾所周知,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。