Delphi  实现Ping命令

unit FtPing;

interface

uses
Windows, SysUtils, Classes, Controls, Winsock, StdCtrls; resourcestring
SICMPRunError = 'ICMP Run Error';
SInitFailed = 'Init Failed. Maybe Winsock Verison Error';
SNoResponse = '[%0:S] No Response';
SInvalidAddr = 'IP Address Error';
SPingResultString = '[%0:S]: Bytes:%1:D Time: %2:Dms TTL:%3:D'; type PCnIPOptionInformation = ^TCnIPOptionInformation;
TCnIPOptionInformation = packed record
TTL: Byte; // Time To Live (used for traceroute)
TOS: Byte; // Type Of Service (usually )
Flags: Byte; // IP header flags (usually )
OptionsSize: Byte; // Size of options data (usually , max )
OptionsData: PAnsiChar; // Options data buffer
end; PCnIcmpEchoReply = ^TCnIcmpEchoReply;
TCnIcmpEchoReply = packed record
Address: DWORD; // replying address
Status: DWORD; // IP status value (see below)
RTT: DWORD; // Round Trip Time in milliseconds
DataSize: Word; // reply data size
Reserved: Word;
Data: Pointer; // pointer to reply data buffer
Options: TCnIPOptionInformation; // reply options
end; TIpInfo = record
Address: Int64;
IP: string;
Host: string;
end; TOnReceive = procedure( Sender: TComponent; IPAddr, HostName: string; TTL, TOS: Byte ) of object; TOnError = procedure( Sender: TComponent; IPAddr, HostName: string; TTL, TOS: Byte; ErrorMsg: string ) of object; //==============================================================================
// Ping 通讯类
//============================================================================== { TFtPing } TFtPing = class( TComponent )
{* 通过调用ICMP.DLL库中的函数来实现Ping功能。}
private
hICMP: THANDLE;
FRemoteHost: string;
FRemoteIP: string;
FIPAddress: Int64;
FTTL: Byte;
FTimeOut: DWord;
FPingCount: Integer;
FDelay: Integer;
FOnError: TOnError;
FOnReceived: TOnReceive;
FDataString: string;
FWSAData: TWSAData;
FIP: TIpInfo; procedure SetPingCount( const Value: Integer );
procedure SetRemoteHost( const Value: string );
procedure SetTimeOut( const Value: DWord );
procedure SetTTL( const Value: Byte );
procedure SetDataString( const Value: string );
procedure SetRemoteIP( const Value: string );
function PingIP_Host( const aIP: TIpInfo; const Data; Count: Cardinal; var aReply: string ): Integer;
{* 以设定的数据Data(无类型缓冲区)Ping一次并返回结果。Count表示数据长度 }
function GetReplyString( aResult: Integer; aIP: TIpInfo; pIPE: PCnIcmpEchoReply ): string;
{* 返回结果字符串。}
function GetDataString: string;
function GetIPByName( const aName: string; var aIP: string ): Boolean;
{* 通过机器名称获取IP地址}
function SetIP( aIPAddr, aHost: string; var aIP: TIpInfo ): Boolean;
{* 通过机器名称或IP地址填充完整IP信息}
protected public
constructor Create( AOwner: TComponent ); override;
destructor Destroy; override; function IsOnline: Boolean; function Ping( var aReply: string ): Boolean;
{* 进行循环Ping,循环次数在PingCount属性中指定。}
function PingOnce( var aReply: string ): Boolean; overload;
{* 以设定的数据Ping一次并返回结果。}
function PingOnce( const aIP: string; var aReply: string ): Boolean; overload;
{* 向指定IP进行一次Ping并返回结果。}
function PingFromBuffer( var Buffer; Count: Longint; var aReply: string ): Boolean;
{* 以参数Buffer的数据Ping一次并读取返回结果。}
published
property RemoteIP: string read FRemoteIP write SetRemoteIP;
{* 要Ping的目标主机地址,只支持ip}
property RemoteHost: string read FRemoteHost write SetRemoteHost;
{* 要ping的目标主机名,有主机名存在时会覆盖 RemoteIP 的内容}
property PingCount: Integer read FPingCount write SetPingCount default ;
{* 调用Ping方法时进行多少次数据发送,默认是4次。}
property Delay: Integer read FDelay write FDelay default ;
{* 相邻两次 Ping 间的时间间隔,单位毫秒,默认 0 也就是不延时}
property TTL: Byte read FTTL write SetTTL;
{* 设置的TTL值,Time to Live}
property TimeOut: DWord read FTimeOut write SetTimeOut;
{* 设置的超时值}
property DataString: string read GetDataString write SetDataString;
{* 欲发送的数据,以字符串形式表示,默认为"CnPack Ping"。}
property OnReceived: TOnReceive read FOnReceived write FOnReceived;
{* Ping一次成功时返回数据所触发的事件}
property OnError: TOnError read FOnError write FOnError;
{* Ping出错时返回的内容和信息。包括目的未知、不可达、超时等。}
end; implementation {$R-} const
SCnPingData = 'FtPack Ping.';
ICMPDLL = 'icmp.dll'; type //==============================================================================
// 辅助过程 从icmp.dll导入的函数
//============================================================================== TIcmpCreateFile = function( ): THandle; stdcall; TIcmpCloseHandle = function( IcmpHandle: THandle ): Boolean; stdcall; TIcmpSendEcho = function( IcmpHandle: THandle;
DestAddress: DWORD;
RequestData: Pointer;
RequestSize: Word;
RequestOptions: PCnIPOptionInformation;
ReplyBuffer: Pointer;
ReplySize: DWord;
TimeOut: DWord ): DWord; stdcall; var
IcmpCreateFile: TIcmpCreateFile = nil;
IcmpCloseHandle: TIcmpCloseHandle = nil;
IcmpSendEcho: TIcmpSendEcho = nil; IcmpDllHandle: THandle = ; procedure InitIcmpFunctions;
begin
IcmpDllHandle := LoadLibrary( ICMPDLL );
if IcmpDllHandle <> then
begin
@IcmpCreateFile := GetProcAddress( IcmpDllHandle, 'IcmpCreateFile' );
@IcmpCloseHandle := GetProcAddress( IcmpDllHandle, 'IcmpCloseHandle' );
@IcmpSendEcho := GetProcAddress( IcmpDllHandle, 'IcmpSendEcho' );
end;
end; procedure FreeIcmpFunctions;
begin
if IcmpDllHandle <> then
FreeLibrary( IcmpDllHandle );
end; //==============================================================================
// Ping 通讯类
//============================================================================== { TFtPing } constructor TFtPing.Create( AOwner: TComponent );
begin
inherited Create( AOwner );
FRemoteIP := '127.0.0.1';
FTTL := ;
FPingCount := ;
FDelay := ;
FTimeOut := ;
FDataString := SCnPingData; hICMP := IcmpCreateFile( ); // 取得DLL句柄
if hICMP = INVALID_HANDLE_VALUE then
begin
raise Exception.Create( SICMPRunError );
end;
end; destructor TFtPing.Destroy;
begin
if hICMP <> INVALID_HANDLE_VALUE then
begin
IcmpCloseHandle( hICMP );
end;
inherited Destroy;
end; procedure TFtPing.SetPingCount( const Value: Integer );
begin
if Value > then
FPingCount := Value;
end; procedure TFtPing.SetRemoteIP( const Value: string );
begin
if FRemoteIP <> Value then
begin
FRemoteIP := Value;
if SetIP( FRemoteIP, '', FIP ) then
begin
FRemoteHost := FIP.Host;
FIPAddress := FIP.Address;
end;
end;
end; procedure TFtPing.SetRemoteHost( const Value: string );
begin
if FRemoteHost <> Value then
begin
// RemoteHost 更改的话,RemoteIP 自动清空
FRemoteHost := Value;
if SetIP( '', FRemoteHost, FIP ) then
begin
FRemoteIP := FIP.IP;
FIPAddress := FIP.Address;
end;
end;
end; procedure TFtPing.SetTimeOut( const Value: DWord );
begin
FTimeOut := Value;
end; procedure TFtPing.SetTTL( const Value: Byte );
begin
FTTL := Value;
end; procedure TFtPing.SetDataString( const Value: string );
begin
FDataString := Value;
end; function TFtPing.GetDataString: string;
begin
if FDataString = '' then
FDataString := SCnPingData;
Result := FDataString;
end; function TFtPing.IsOnline: Boolean;
var
sReply: string;
begin
SetIP( RemoteIP, RemoteHost, FIP );
Result := PingIP_Host( FIP, pointer( FDataString )^, Length( DataString ), sReply ) >= ;
end; function TFtPing.Ping( var aReply: string ): Boolean;
var
iCount, iResult: Integer;
sReply: string;
begin
aReply := '';
iResult := ;
try
SetIP( RemoteIP, RemoteHost, FIP );
for iCount := to PingCount do
begin
iResult := PingIP_Host( FIP, Pointer( FDataString )^, Length( DataString ) * SizeOf( Char ), sReply );
aReply := aReply + ## + sReply;
if iResult < then
Break; if FDelay > then
Sleep( FDelay );
end;
finally
Result := iResult >= ;
end;
end; function TFtPing.PingOnce( var aReply: string ): Boolean;
begin
SetIP( RemoteIP, RemoteHost, FIP );
Result := PingIP_Host( FIP, pointer( FDataString )^, Length( DataString ), aReply ) >= ;
end; function TFtPing.PingOnce( const aIP: string; var aReply: string ): Boolean;
begin
SetIP( aIP, aIP, FIP );
Result := PingIP_Host( FIP, pointer( FDataString )^, Length( DataString ), aReply ) >= ;
end; function TFtPing.PingFromBuffer( var Buffer; Count: Integer; var aReply: string ): Boolean;
begin
SetIP( RemoteIP, RemoteHost, FIP );
Result := PingIP_Host( FIP, Buffer, Count, aReply ) >= ;
end; function TFtPing.PingIP_Host( const aIP: TIpInfo; const Data; Count: Cardinal; var aReply: string ): Integer;
var
IPOpt: TCnIPOptionInformation; // 发送数据结构
pReqData, pRevData: PAnsiChar;
pCIER: PCnIcmpEchoReply;
begin
Result := -;
pReqData := nil; if Count <= then
begin
aReply := GetReplyString( Result, aIP, nil );
Exit;
end;
if aIP.Address = INADDR_NONE then
begin
Result := -;
aReply := GetReplyString( Result, aIP, nil );
Exit;
end; GetMem( pCIER, SizeOf( TCnICMPEchoReply ) + Count );
GetMem( pRevData, Count );
try
FillChar( pCIER^, SizeOf( TCnICMPEchoReply ) + Count, ); // 初始化接收数据结构
pCIER^.Data := pRevData;
GetMem( pReqData, Count );
Move( Data, pReqData^, Count ); // 准备发送的数据
FillChar( IPOpt, Sizeof( IPOpt ), ); // 初始化发送数据结构
IPOpt.TTL := FTTL; try //Ping开始
if WSAStartup( MAKEWORD( , ), FWSAData ) <> then
raise Exception.Create( SInitFailed );
if IcmpSendEcho( hICMP, //dll handle
aIP.Address, //target
pReqData, //data
Count, //data length
@IPOpt, //addree of ping option
pCIER,
SizeOf( TCnICMPEchoReply ) + Count, //pack size
FTimeOut //timeout value
) <> then
begin
Result := ; // Ping正常返回
if Assigned( FOnReceived ) then
FOnReceived( Self, aIP.IP, aIP.Host, IPOpt.TTL, IPOpt.TOS );
end
else
begin
Result := -; // 没有响应
if Assigned( FOnError ) then
FOnError( Self, aIP.IP, aIP.Host, IPOpt.TTL, IPOpt.TOS, SNoResponse );
end;
except
on E: Exception do
begin
Result := -; // 发生错误
if Assigned( FOnError ) then
FOnError( Self, aIP.IP, aIP.Host, IPOpt.TTL, IPOpt.TOS, E.Message );
end;
end;
finally
WSACleanUP;
aReply := GetReplyString( Result, aIP, pCIER );
if pRevData <> nil then
begin
FreeMem( pRevData ); // 释放内存
pCIER.Data := nil;
end;
if pReqData <> nil then
FreeMem( pReqData ); //释放内存
FreeMem( pCIER ); //释放内存
end;
end; function TFtPing.GetReplyString( aResult: Integer; aIP: TIpInfo;
pIPE: PCnIcmpEchoReply ): string;
var
sHost: string;
begin
Result := SInvalidAddr;
case aResult of
-: Result := SICMPRunError;
-: Result := SInvalidAddr;
-: Result := Format( SNoResponse, [ RemoteHost ] );
else
if pIPE <> nil then
begin
sHost := aIP.IP;
if aIP.Host <> '' then
sHost := aIP.Host + ': ' + sHost;
Result := ( Format( SPingResultString, [ sHost, pIPE^.DataSize, pIPE^.RTT,
pIPE^.Options.TTL ] ) );
end;
end;
end; function TFtPing.GetIPByName( const aName: string;
var aIP: string ): Boolean;
var
pHost: PHostEnt;
FWSAData: TWSAData;
sName: array[ .. ] of AnsiChar;
begin
Result := False;
// StrPCopy(sName, {$IFDEF DELPHI12_UP}AnsiString{$ENDIF}(aName));
StrPCopy( sName, AnsiString( aName ) );
aIP := '';
if aName = '' then
Exit; WSAStartup( $, FWSAData );
try
pHost := GetHostByName( @sName );
Result := pHost <> nil;
if Result then
// aIP := {$IFDEF DELPHI12_UP}string{$ENDIF}(inet_ntoa(PInAddr(pHost^.h_addr_list^)^));
aIP := string( inet_ntoa( PInAddr( pHost^.h_addr_list^ )^ ) );
finally
WSACleanup;
end;
end; function TFtPing.SetIP( aIPAddr, aHost: string; var aIP: TIpInfo ): Boolean;
var
pIPAddr: PAnsiChar;
begin
Result := False;
aIP.Address := INADDR_NONE;
aIP.IP := aIPAddr;
aIP.Host := aHost;
if aIP.IP = '' then
begin
if ( aIP.Host = '' ) or ( not GetIPByName( aIP.Host, aIP.IP ) ) then
Exit;
end; GetMem( pIPAddr, Length( aIP.IP ) + );
try
ZeroMemory( pIPAddr, Length( aIP.IP ) + );
// StrPCopy(pIPAddr, {$IFDEF DELPHI12_UP}AnsiString{$ENDIF}(aIP.IP));
StrPCopy( pIPAddr, AnsiString( aIP.IP ) );
aIP.Address := inet_addr( PAnsiChar( pIPAddr ) ); // IP转换成无点整型
finally
FreeMem( pIPAddr ); // 释放申请的动态内存
end;
Result := aIP.Address <> INADDR_NONE;
end; initialization
InitIcmpFunctions; finalization
FreeIcmpFunctions; end. {
调用方法
procedure TForm1.Button1Click( Sender: TObject );
var
FtPing: TFtPing;
aReply: string;
begin
FtPing := TFtPing.Create( nil );
try
FtPing.RemoteIP := Edit1.Text;
if FtPing.Ping( aReply ) then
begin
Memo1.Lines.Add( '网络畅通!' )
end
else
begin
Memo1.Lines.Add( '网络异常~~>|<~~' )
end;
finally
FtPing.Free;
end;
end; }

正则取匹配IP地址

 Reg:=TPerlRegEx.Create;
Reg.Subject:=pos.ServerUrl;
Reg.RegEx:='((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)'; if reg.Match then
IP:=Reg.MatchedText
else
//TODO 没有获取到IP地址

Delphi 实现Ping命令的更多相关文章

  1. [delphi]运行cmd命令,并取得输出字符

     http://blog.csdn.net/nerdy/article/details/8969189 [delphi]运行cmd命令,并取得输出字符 标签: delphiCMD命令 2013-05- ...

  2. [转]Delphi执行CMD命令

    今天看到有人在问用代码执行CMD命令的问题,就总结一下用法,也算做个备忘. Delphi中,执行命令或者运行一个程序有2个函数,一个是winexec,一个是shellexecute.这两个大家应该都见 ...

  3. Docker的ubuntu镜像安装的容器无ifconfig和ping命令的解决

    Docker的Ubuntu镜像安装的容器无ifconfig命令和ping命令 解决: apt-get update apt install net-tools       # ifconfig apt ...

  4. windows 环境和linux环境下 ping命令的区别:

    Ping 是Windows自带的一个DOS命令.利用它可以检查网络是否能够连通,用好它可以很好地帮助我们分析判定网络故障.该命令可以加许多参数使用,键入Ping按回车即可看到详细说明.Ping 命令可 ...

  5. ping命令执行过程详解

    [TOC] ping命令执行过程详解 机器A ping 机器B 同一网段 ping通知系统建立一个固定格式的ICMP请求数据包 ICMP协议打包这个数据包和机器B的IP地址转交给IP协议层(一组后台运 ...

  6. ping命令脚本实现显示网络状态、学生姓名、学号

    #!/bin/bash a=. ####定义一个固定变量 h=(wanghao xieyunshen 刘桃) ####定义数组 ..} ####for循环,后面的in是条件即从多少循环到多少 do # ...

  7. [小菜随笔]python tkinter实现简单的ping命令

    本文主要是介绍python图形界面上的按键与实际功能的对接,其实编程掌握了基础之后的学习应该都是靠自己去挖掘其他的 在网上发现多半教程都是2的,故本文使用的是python3.5,其实也没什么区别,就有 ...

  8. cmd中用PING命令时,出现'Ping' 不是内部或外部命令 解决方案

    在cmd中用PING命令时,出现'Ping' 不是内部或外部命令,也不是可运行的程序或批处理文件.先了解一下内容:1.可执行文件.命令文件和批处理文件以.exe或者.com或者.bat为扩展名的文件分 ...

  9. ping命令

    ping命令能够用于判断一个主机是否可达或者是否存活.它的工作原理就像潜水艇的探测原理一样.该命令通过向目标计算机发送一个数据包,请求目标计算机回送该数据包以表明自己还存活着.同时该命令还能够知道数据 ...

随机推荐

  1. 【剑指OFFER】链表中倒数第k个结点

    [问题描述] 输入一个链表,输出该链表中倒数第k个结点. 时间限制:1秒 空间限制:32768K [AC代码] p先走k步,q再走,这样p和q的距离就是k了,等p走到尽头,那么q自然就到了倒数第k个位 ...

  2. Oulipo POJ - 3461(kmp,求重叠匹配个数)

    Problem Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, w ...

  3. Redis 使用指南:深度解析 info 命令

    Redis 是一个使用  ANSI C 编写的开源.基于内存.可选持久性的键值对存储数据库,被广泛应用于大型电商网站.视频网站和游戏应用等场景,能够有效减少数据库磁盘 IO, 提高数据查询效率,减轻管 ...

  4. Java通过Socket和动态代理实现简易RPC框架

    本文转自Dubbo作者梁飞大神的CSDN(https://javatar.iteye.com/blog/1123915),代码简洁,五脏俱全. 1.首先实现RpcFramework,实现服务的暴露与引 ...

  5. 路由组件传参-props解耦方式(主要)

    在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性. 使用 props 将组件和路由解耦: 取代与 $route 的耦合 const ...

  6. C++通用框架和库

    C++通用框架和库 来源 https://www.cnblogs.com/skyus/articles/8524408.html 关于 C++ 框架.库和资源的一些汇总列表,内容包括:标准库.Web应 ...

  7. 关于Mybatis的几件小事(一)

    一.Mybatis简介 1.Mybatis简介 MyBatis是支持定制化SQL.存储过程以及高级映射的优秀的持久层框架. MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集. M ...

  8. span元素

    <span>标签属于行内元素(inline),所以无法设置高度和宽度: 如果需要改变其宽高,就需要将其转变为块体元素(block)或行内块体元素(inle-block)

  9. 一种无法被Dump的jar包加密保护解决方案

    作者: 我是小三 博客: http://www.cnblogs.com/2014asm/ 由于时间和水平有限,本文会存在诸多不足,希望得到您的及时反馈与指正,多谢! 工具环境: windwos10.I ...

  10. java之JVM学习--简单了解GC算法

    JVM内存组成结构: (1)堆 所有通过new创建的对象都是在堆中分配内存,其大小可以通过-Xmx和-Xms来控制,堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区.Sur ...