Trace 命令可以实现跟踪目的地经过的IP地址.请问Trace如何实现的?
回复人:forgot2000 | 忘记2000年
program TraceRoute;
uses
Forms,
MainForm in 'MainForm.pas' {TraceRouteForm},
ICMP_Define in 'ICMP_Define.pas';
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TTraceRouteForm, TraceRouteForm);
Application.Run;
end.
//ICMP_Define.PAS
unit ICMP_Define;
interface
uses winsock;
type
DWORD=LongWord;
THandle=LongWord;
THostTraceMultiReply=record
dwError : DWORD; //GetLastError for this host
Address : in_addr; //The IP address of the replier
minRTT : DWORD; //Minimum round trip time in milliseconds
avgRTT : DWORD; //Average round trip time in milliseconds
maxRTT : DWORD; //Maximum round trip time in milliseconds
end;
THostTraceSingleReply=record
dwError:DWORD; //GetLastError for this replier
Address:in_addr; //The IP address of the replier
RTT:DWORD; //Round Trip time in milliseconds for this replier
end;
PIPOptionInformation = ^TIPOptionInformation;
TIPOptionInformation =
record
TTL: Byte;
TOS: Byte;
Flags: Byte;
OptionsSize: Byte;
OptionsData: PChar;
end;
PIcmpEchoReply = ^TIcmpEchoReply;
TIcmpEchoReply =
record
Address: DWORD;
Status: DWORD;
RTT: DWORD;
DataSize:Word;
Reserved: Word;
Data: Pointer;
Options: TIPOptionInformation;
end;
const
ULONG_MAX=1024;
function IcmpCreateFile():THandle;stdcall external 'ICMP.dll';
function IcmpCloseHandle(Handle:THandle):Boolean;stdcall external 'ICMP.dll';
function IcmpSendEcho(Handle:THandle;DestAddr:DWORD;
RequestData: Pointer;RequestSize: Word;RequestOptions: PIPOptionInformation;
ReplyBuffer: Pointer;ReplySize: DWORD;Timeout: DWORD): DWORD;stdcall external 'ICMP.dll';
implementation
end.
//主菜单
unit MainForm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,Winsock,ICMP_Define;
type
TTraceRouteForm = class(TForm)
Label1: TLabel;
edtIP: TEdit;
btnTracert: TButton;
memResult: TMemo;
procedure btnTracertClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure Tracert(dwAddr:DWORD;dwPingsPerHost:DWORD);
function Ping(dwAddr:DWORD;TimeOut:Word;var htsr:THostTraceSingleReply;nTTL:Byte):boolean;
end;
var
TraceRouteForm: TTraceRouteForm;
implementation
{$R *.DFM}
procedure TTraceRouteForm.btnTracertClick(Sender: TObject);
var
WSAData:TWSAData;
dwAddr:DWORD;
hp:phostent;
begin
//init winsock dll
if (WSAStartup(MAKEWORD(2,0),WSAData)<>0) then
raise Exception.Create('Winsock Version Error');
ZeroMemory(Addr(dwAddr),sizeof(dwAddr));
//resolve IP
//convert form dotted address
dwAddr:=inet_addr(pchar(edtIP.text));
if (dwAddr=INADDR_NONE) then
begin
hp:=gethostbyname(pchar(edtIP.Text));
if hp=NIL then
begin
memResult.Lines.Add('Failed to resolve host IP');
Exit//Failed to resolve host;
end
else
CopyMemory(Addr(dwAddr),hp.h_addr^,hp.h_length);
end;
memResult.Lines.Add(Format('Resolve Target: %d.%d.%d.%d',[LoByte(LoWord(dwAddr)),
HiByte(LoWord(dwAddr)),
LoByte(HiWord(dwAddr)),
HiByte(HiWord(dwAddr))]));
//trace route
//icmp function must be declared.
Tracert(dwAddr,1);
//release winsock dll
WSACleanUP;
end;
procedure TTraceRouteForm.Tracert(dwAddr:DWORD;dwPingsPerHost:DWORD);
var
dwTimeOut : DWORD;
nHops : Byte;
nPings : Byte;
bReachedHost : Boolean;
i,j : Byte;
htrr : THostTraceMultiReply;
htsr : THostTraceSingleReply;
totalRTT : DWORD;
bPingError : Boolean;
Top
回复人:forgot2000 | 忘记2000年
begin
//set init value
dwTimeOut:=3000;//this value changed according the net condition
nHops:=30;
nPings:=3;
bReachedHost:=false;
//update show.
memResult.Lines.Add(Format('Tracing route to %s '#13#10'over a maximum of %d hpos',
[edtIP.Text,nHops]));
for i:=1 to nHops do
begin
if bReachedHost then
begin
memResult.Lines.Add('Trace Complete');
Break;
end;
htrr.dwError := 0;
htrr.minRTT := ULONG_MAX;
htrr.avgRTT := 0;
htrr.maxRTT := 0;
//Iterate through all the pings for each host
totalRTT := 0;
htsr.Address.S_addr := 0;
htsr.dwError := 0;
bPingError:=false;
for j:=1 to dwPingsPerHost do
begin
if bPingError Then break;
if (Ping(dwAddr,dwTimeOut,htsr,i))then
if (htsr.dwError=0)then
begin
inc(totalRTT,htsr.RTT);//acumulate total time
//Store away the RTT etc
if (htsr.RTT<htrr.minRTT)then htrr.minRTT:=htsr.RTT;
if (htsr.RTT>htrr.maxRTT)then htrr.maxRTT:=htsr.RTT;
end //if (htsr.dwError=0)then
else //if (htsr.dwError=0)then
begin
htrr.dwError:=htsr.dwError;
bPingError:=true;
end
else//if (Ping(dwAddr,dwTimeOut,htsr,i))then
begin//ping failed
memResult.Lines.Add(inttostr(i)+' Ping failed');
end;
end;// for j:=1 to dwPingsPerHost do
htrr.Address := htsr.Address;
if (htrr.dwError = 0)then
htrr.avgRTT := Round(totalRTT / dwPingsPerHost)
else
begin
htrr.minRTT := 0;
htrr.avgRTT := 0;
htrr.maxRTT := 0;
end;
//show trace result here
if htrr.dwError=0 then
begin
memResult.Lines.Add(Format('%d %d ms %d ms %d ms %d.%d.%d.%d'#13#10,
[i,
htrr.minRTT,
htrr.avgRTT,
htrr.maxRTT,
ord(htrr.Address.S_un_b.s_b1),
ord(htrr.Address.S_un_b.s_b2),
ord(htrr.Address.S_un_b.s_b3),
ord(htrr.Address.S_un_b.s_b4)]));
memResult.update;
end
else
memResult.Lines.Add(Format('%d Error:%d',[i,htrr.dwError]));
memResult.Update;
if (dwaddr=htrr.Address.S_addr)then
//reach the final host
bReachedHost:=true;
end;// of for i:=1 to nHops do
end;
function TTraceRouteForm.Ping(dwAddr:DWORD;TimeOut:Word;var htsr:THostTraceSingleReply;nTTL:Byte):boolean;
var
IPOpt:TIPOptionInformation;// IP Options for packet to send
pReqData,pRevData:PChar;
pIPE:PIcmpEchoReply;// ICMP Echo reply buffer
FSize: DWORD;
BufferSize:DWORD;
temp:Integer;
hICMP:THandle;
begin
Result:=false;
hICMP:=IcmpCreateFile();
if hICMP=INVALID_HANDLE_VALUE then
begin
//Could not get a valid icmp handle
exit;
end;
FSize := 40; //package size
BufferSize := SizeOf(TICMPEchoReply) + FSize;
GetMem(pRevData,FSize);
GetMem(pIPE,BufferSize);
//set up the option structure
ZeroMemory(@IPOpt,SizeOf(TIPOptionInformation));
IPOpt.TTL:=nTTL;
FillChar(pIPE^, SizeOf(pIPE^),0);
pIPE^.Data := pRevData;
GetMem(pReqData,5);//data package size = 5 byte
FillChar(pReqData^,5,65);
temp:=IcmpSendEcho(hICMP, dwAddr, pReqData, 5,
@IPOpt,pIPE, BufferSize, TimeOut);
if temp=0 then
begin
htsr.dwError:=GetLastError();
end
else
begin
//ping success,copy info to return structure;
htsr.Address.S_addr:=pIPE^.Address;
htsr.RTT:=pIPE^.RTT;
Result:=true;
end;
//Free up the memory we allocated
FreeMem(pRevData);
FreeMem(pIPE);
//Close the ICMP handle
IcmpCloseHandle(hIcmp);
end;
procedure TTraceRouteForm.FormCreate(Sender: TObject);
begin
//update view
MemResult.Font.Color:=clHighlightText;
MemResult.Font.Name:='Terminal';
MemResult.Font.Size:=10;
MemResult.Color:= clNone;
end;
end.