⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 getmac.pas

📁 通过IP取MAC等资料的控件
💻 PAS
字号:
[:D]设置IP后调用GetMac方法,取结果代码放在OnReceive事件里。 
原来写构件这么有趣! 


unit GetMac; 

interface 

uses 
  Windows, Messages, SysUtils, Classes, WinSock, Dialogs; 
const 
  WM_SOCK = WM_USER + $0001;    //自定义windows消息 
  UDPPort = 6767;          //设定本端UDP端口号 
  NBTPort = 137;            //设定对端UDP端口号 

var 
  MyByte:            array [0..3]of byte; 
  WAIT_ACK_EVENT:    Thandle; 
  MySock: TSocket; 
  MyAddr: TSockAddr; 
  FSockAddrIn : TSockAddrIn; 

type 
  TGetMac = class(TComponent) 
  private 
    { Private declarations } 
    FIP:string;          //输入的欲取得MAC地址的机子的IP地址 
    FWorkGroup:string;  //返回的工作组名称 
    FHostName:string;    //返回的主机名 
    FUserName:string;    //返回的用户名 
    FMacAddress:string;  //返回的网卡Mac地址 
    FHandle: HWnd;      //非可视构件消息处理使用 
    FOnReceive: TNotifyEvent;//接收到返回结果触发的事件 

    Binded: Boolean; 

    //对输入的IP地址进行合法性检查并赋给FIP变量 
    procedure SetFIP(Value: string); 
    //判断IP地址是否合法 
    Function IsLegalIP(IP:string):Boolean; 
    //将IP地址分成四部份 
    procedure GetAddrByte(IP:string;var B:array of byte); 

  protected 
    { Protected declarations } 
    procedure ReceiveReturn; dynamic; 
    //利用消息实时获知UDP消息 
    procedure ReadData(var Msg: TMessage);//message WM_SOCK; 
    //分析返回的消息内容 
    procedure RecvNbMsg(buffer: Array of byte;len:integer;IP:string); 
  public 
    { Public declarations } 
    procedure GetMac;  //先对IP属性赋值后调用此方法取得相关资料 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 

  published 
    { Published declarations } 
    property IP: string read FIP write SetFIP; 
    property WorkGroup: string read FWorkGroup;// write FWorkGroup; 
    property UserName: string read FUserName;// write FUserName; 
    property HostName: string read FHostName;// write FHostName; 
    property MacAddress: string read FMacAddress;// write FMacAddress; 
    property OnReceive: TNotifyEvent read FOnReceive write FOnReceive; 
  end; 

procedure Register; 

implementation 

//接收到返回的数据后内部处理完毕执行用户定义的代码 
procedure TGetMac.ReceiveReturn; 
begin 
  if Assigned(FOnReceive) then FOnReceive(Self); 
end; 

//检测输入的IP地址是否合法并赋值给FIP变量 
procedure TGetMac.SetFIP(Value: string); 
begin 
    if (not IsLegalIP(Value)) then 
    begin 
        ShowMessage('非法IP地址!'); 
        FIP:='127.0.0.1'; 
        exit; 
    end 
    else 
    begin 
        GetAddrByte(Value,MyByte); 
        FIP:=format('%d.%d.%d.%d',[MyByte[0],MyByte[1],MyByte[2],MyByte[3]]); 
    end; 

end; 

//判断IP地址是否合法 
Function TGetMac.IsLegalIP(IP:string):Boolean; 
begin 

  if inet_addr(pchar(IP))=INADDR_NONE then 
  begin 
    Result:=False; 
    exit; 
  end 
  else result:=true; 

end; 

//将IP地址分成四部份 
procedure TGetMac.GetAddrByte(IP:string;var B:array of byte); 
var i,j:integer; 
    sTemp:string; 
begin 

  sTemp:=''; 
  j:=0; 
  IP:=IP+'.'; 
  for i:=1 to length(IP)do 
  begin 
    if IP[i]<>'.' then sTemp:=sTemp+IP[i] 
    else 
    begin 
      B[j]:=byte(strtoint(sTemp)); 
      inc(j); 
      sTemp:=''; 
    end; 
  end; 

end; 

//开始取网卡地址 
procedure TGetMac.GetMac; 
//欲发送的数据包内容 
const NbtstatPacket:array[0..49]of byte 
      =($0,$0,$0,$0,$0,$1, 
      $0,$0,$0,$0,$0,$0,$20,$43,$4b, 
      $41,$41,$41,$41,$41,$41,$41,$41, 
      $41,$41,$41,$41,$41,$41,$41,$41, 
      $41,$41,$41,$41,$41,$41,$41,$41, 
      $41,$41,$41,$41,$41,$41,$0,$0,$21,$0,$1); 
var 
    len: integer; 
    TempWSAData: TWSAData; 
begin 
    if not Binded then begin 
        // 初始化SOCKET,0成功,使用WinSock1.1版本$0001是1.0版本$0002是2.0版本 
        if WSAStartup($0101, TempWSAData)<>ERROR_SUCCESS then 
            ShowMessage('启动错误'); 

        MySock := Socket(AF_INET, SOCK_DGRAM, 0); 
        if (MySock = INVALID_SOCKET) then  //Socket创建失败 
        begin 
              ShowMessage(inttostr(WSAGetLastError())+'  Socket创建失败!'); 
              CloseSocket(MySock); 
        end; 
        //本机SockAddr绑定 
        MyAddr.sin_family := AF_INET; 
        MyAddr.sin_addr.S_addr := INADDR_ANY; 
        MyAddr.sin_port := htons(UDPPORT); 
        if Bind(MySock, MyAddr, sizeof(MyAddr)) <> 0  then 
          begin 
            ShowMessage('绑定错误!'); 
            Binded:=False; 
          end 
        else Binded:=True; 

        WSAAsyncSelect(MySock, FHandle, WM_SOCK, FD_READ); 
        WAIT_ACK_EVENT:=CreateEvent(nil,true,false,pchar('WAIT_ACK')); 
        //ResetEvent(WAIT_ACK_EVENT);} 
    end; 

    //向对方主机UDP指定的端口发送数据包 
    FSockAddrIn.SIn_Addr.S_addr := inet_addr(pchar(FIP)); 
    FSockAddrIn.SIn_Family := AF_INET; 
    FSockAddrIn.SIn_Port := htons(NBTPORT); 
    len := SendTo(MySock, NbtstatPacket[0],50, 0, FSockAddrIn, sizeof(FSockAddrIn)); 
    //if (WSAGetLastError() <> WSAEWOULDBLOCK) and (WSAGetLastError() <> 0) then showmessage(inttostr(WSAGetLastError())); 
    if len = SOCKET_ERROR then ShowMessage('SOCKET_ERROR,发送失败!'); 
    if len <> 50 then ShowMessage('数据没有全部发送!'); 

//    WaitForSingleObject(WAIT_ACK_EVENT,WaitTime); 
    ResetEvent(WAIT_ACK_EVENT); 

end; 

//接收返回的消息数据 
procedure TGetMac.ReadData(var Msg:TMessage); 
var 
  buffer: Array [1..500] of byte; 
  flen,len: integer; 
  Event: word; 
  IP:string; 
begin 
    if Msg.msg<>WM_SOCK then exit; 
    flen:=sizeof(FSockAddrIn); 
    FSockAddrIn.SIn_Family := AF_INET; 
    FSockAddrIn.SIn_Port := htons(NBTPORT); 
    Event := WSAGetSelectEvent(Msg.LParam); 
    if Event = FD_READ then 
    begin 
          len := recvfrom(MySock, buffer, sizeof(buffer), 0, FSockAddrIn, flen); 
          if len> 0 then 
          begin 

            //FSockAddrIn.sin_addr.S_un_b.s_b1 
            with FSockAddrIn.sin_addr.S_un_b 
            do IP:=format('%d.%d.%d.%d',[ord(s_b1),ord(s_b2),ord(s_b3),ord(s_b4)]); 

            RecvNbMsg(buffer,len,IP); 

          end; 
          SetEvent(WAIT_ACK_EVENT); 

    end; 
    //触发事件,执行用户指定的代码 
    ReceiveReturn; 
end; 

//分析返回的消息 
procedure TGetMac.RecvNbMsg(buffer: Array of byte;len:integer;IP:string); 
var 
    TempStr:string; 
    i,j,pos,name_num: integer; 
begin 

  name_num:=0; 
  for i:=1 to len do 
  begin 
    if((buffer[i]=$21)and(buffer[i+1]=$00)and(buffer[i+2]=$01)) 
    then 
    begin 
      name_num:=buffer[i+9]; 
      break; 
    end; 
  end; 

  if name_num=0 then exit; 
  pos:=i+10; 

  TempStr:=''; 
  for i:=pos to (pos+18*name_num-1) do 
  begin 
    if (((i-pos)mod 18) =0) then 
    begin 
      for j:=0 to 14 do 
      begin 
        if trim(char(buffer[i+j]))='' then buffer[i+j]:=ord(' '); 
        TempStr:=TempStr+char(buffer[i+j]); 
      end; 

    if (buffer[i+16] and $80)=$80 then 
    begin 
      if buffer[i+15]=$0 then FWorkGroup:=TempStr; 
    end 
    else 
    begin 
      if buffer[i+15]=$20 then FHostName:=TempStr 
      else 
      if buffer[i+15]=$3 then FUserName:=TempStr; 

    end; 
    TempStr:=''; 
    end; 
  end; 
  //取得网卡地址 
  for i:=0 to 5 do 
  begin 
    TempStr:=TempStr+format('%.2x.',[buffer[i+pos+18*name_num]]); 
  end; 
  delete(TempStr,length(TempStr),1); 
  FMacAddress:=TempStr; 

end; 

//构件创建 
constructor TGetMac.Create; 
begin 
    inherited Create(AOwner); 

    FHandle := Classes.AllocateHWnd(ReadData); 

    //初始化属性值 
    FIP:='127.0.0.1'; 
    FUserName:=''; 
    FHostName:=''; 
    FWorkGroup:=''; 
    FMacAddress:=''; 
    Binded:=False; 
end; 

//构件消毁 
destructor TGetMac.Destroy; 
begin 
  CloseSocket(MySock); 
  WSACleanup(); 
  Classes.DeallocateHWnd(FHandle); 
  inherited Destroy; 
end; 

//登记控件 
procedure Register; 
begin 
  RegisterComponents('FastNet', [TGetMac]); 
end; 

end. 
  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -