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

📄 umainform.~pas

📁 定时扫描局域网络中的电脑的Mac地址情况
💻 ~PAS
字号:
unit UMainForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, winsock, ExtCtrls,UIPMacManager;

const
  WM_SOCK = WM_USER + 1;     //自定义windows消息
  UDPPORT = 6767;            //设定UDP端口号
  NBTPORT = 137;
  RegisterIPHeadFileName = 'RegisterIPHeadFileNames.txt';
type


  TMainForm = class(TForm)
    Edit1: TEdit;
    Label1: TLabel;
    Button1: TButton;
    Edit2: TEdit;
    Label2: TLabel;
    Timer1: TTimer;
    Button2: TButton;
    Button3: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    IPHeadMemo: TMemo;
    Label3: TLabel;
    GroupBox1: TGroupBox;
    RmodeNT: TRadioButton;
    Rmode98: TRadioButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);


  private
    ScanTimerEnabled:boolean;

    FSocket: TSocket;
    Socketaddr: TSockAddr;
    FSockAddrIn : TSockAddrIn; //利用消息实时获知UDP消息
    WAIT_ACK_EVENT:       Thandle;
    procedure ReadData(var Message: TMessage); message WM_SOCK;
    procedure InitSocket;
    procedure ScanIP_UDP(IP:string;b:array of byte);
    procedure WinNTScanIP;
    procedure Win98ScanIP;
    procedure RegistIpHead;

  public
    { Public declarations }
    procedure LogStr(s:string);
  end;
  Function GetMac(buffer: Array of byte;pos:integer;name_num:integer):string;
  Function GetGroupHostName(buffer: Array of byte;pos:integer;name_num:integer):string;
  procedure GetInfo(buffer: Array of byte;len:integer;var iPos:integer;var NameNum:integer);

var
  MainForm: TMainForm;

implementation
uses UFunctions,UMacFunction,UScanThread;
const NbtstatPacket:array[0..49]of byte
      =($0,$0,$0,$10,$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);
     // IPHead:array [0..0]of string=('192.168.101.');

      OnLineMaxCountPerThread=50;
      OffLineMaxCountPerThread=30;
var   IPHead:array of string;

{$R *.dfm}

procedure TMainForm.LogStr(s:string);
begin
   Memo2.Lines.BeginUpdate;
   if(Memo2.Lines.Count>500) then
      Memo2.Lines.Clear;
   Memo2.Lines.Insert(0,s);
   Memo2.Lines.EndUpdate;
end;
procedure TMainForm.Button1Click(Sender: TObject);
var
  status, macaddr: olevariant;
begin
  dogetmacbyip(edit1.Text, macaddr, status);
  edit2.Text:= macaddr ;
end;


function GetAppPath:String;
begin
    GetAppPath:=ExtractFilePath(Application.ExeName);
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
   if FileExists(GetAppPath+RegisterIPHeadFileName) then
      IPHeadMemo.Lines.LoadFromFile(GetAppPath+RegisterIPHeadFileName);
   IPMacManager:=TIPMacManager.Create(GetAppPath+ScanResultFileName);
   ScanTimerEnabled:=false;
   Timer1.Enabled:=ScanTimerEnabled;
   InitSocket;

end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
   ScanTimerEnabled:=false;
   ThreadStop:=not ScanTimerEnabled;
   self.Timer1.Enabled:=false;
   if(IPMacManager<>nil) then
      FreeAndNil(IPMacManager);
   if(ThreadCount>0) then
      Delay(1000);
   SetLength(IPHead, 0);
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin

   CloseSocket(FSocket);
   ScanTimerEnabled:=false;
   ThreadStop:=not ScanTimerEnabled;
   self.Timer1.Enabled:=false;
   IPHeadMemo.Lines.SaveToFile(GetAppPath+RegisterIPHeadFileName);
end;

procedure ScanIP(IP:string );
//var aThread:TScanThread;
begin
     TScanThread.Create(IP,True,True);
end;

procedure TMainForm.RegistIpHead;
var i:integer;
begin
    for i:=IPHeadMemo.Lines.Count-1 downto 0 do
    begin
        IPHeadMemo.Lines[i]:=trim(IPHeadMemo.Lines[i]);
        if IPHeadMemo.Lines[i]='' then
            IPHeadMemo.Lines.Delete(i);
    end;
    SetLength(IPHead, IPHeadMemo.Lines.Count);
    for i:=Low(IPHead) to High(IPHead) do
    begin
       IPHead[i]:=IPHeadMemo.Lines[i];
    end;
end;
procedure TMainForm.WinNTScanIP;
var i,j,perOnLineCount,perOffLineCount:integer;
    IP:string;
    OnLineIP:string;
    OffLineIP:string;
begin
perOnLineCount:=OnLineMaxCountPerThread;
      perOffLineCount:=OffLineMaxCountPerThread;

      RegistIpHead;
      for i:=Low(IPHead) to High(IPHead) do
      begin
          OffLineIP:='';
          OnLineIP:='';
          if ThreadStop then break;
          for j:=1 to 254 do
          begin
              if ThreadStop then break;
              IP:=IPHead[i]+inttostr(j);
              application.ProcessMessages;
              if(IPMacManager.IsOnLine(IP)) then
              begin
                OnLineIP:=OnLineIP+','+IP;
                dec(perOnLineCount);
              end
              else
              begin
                OffLineIP:=OffLineIP+','+IP;
                dec(perOffLineCount);
              end;

              if(perOnLineCount=0) or (j=254) then
              begin
                   ScanIP(OnLineIP);
                   OnLineIP:='';
                   perOnLineCount:=OnLineMaxCountPerThread;
                   //delay(100);
              end;
              if(perOffLineCount=0) or (j=254) then
              begin
                   ScanIP(OffLineIP);
                   OffLineIP:='';
                   perOffLineCount:=OffLineMaxCountPerThread;
                   //delay(100);
              end;
          end;

      end;

end;

procedure TMainForm.Win98ScanIP;
var i,j,k:integer;
    IP:string;
begin
      k:=0;
      RegistIpHead;
      for i:=Low(IPHead) to High(IPHead) do
      begin
          for j:=1 to 254 do
          begin

              if not ScanTimerEnabled then exit;
              inc(k);
              IP:=IPHead[i]+inttostr(j);
              ScanIP_UDP(IP,NbtstatPacket);
              application.ProcessMessages;
              //Delay(100);

          end;
          //Delay(20);
          //application.ProcessMessages;
      end;
      //LogStr('-------- '+inttostr(k)+'-----------');


end;
procedure TMainForm.Timer1Timer(Sender: TObject);
begin
    LogStr('ScanTimer Start-------------------');
    RegistIpHead;
    if(ThreadCount>(High(IPHead)+1)*3) then exit;
    Timer1.Enabled:=false;

    try
       if RmodeNT.Checked then
          WinNTScanIP
       else
          Win98ScanIP;
    finally
      Timer1.Enabled:=ScanTimerEnabled;
    end;
    LogStr('ScanTimer End--------------------');
end;

procedure TMainForm.Button2Click(Sender: TObject);
begin
   ScanTimerEnabled:=not ScanTimerEnabled;
   Timer1.Enabled:=ScanTimerEnabled;
   ThreadStop:=not ScanTimerEnabled;
   if(ScanTimerEnabled) then
     Button2.Caption:='停止定时检查'
   else
     Button2.Caption:='开始定时检查';
   if(ScanTimerEnabled) then
     Timer1Timer(sender);
end;

procedure TMainForm.Button3Click(Sender: TObject);
begin
   if(IPMacManager<>nil) then
     self.Memo1.Text:=IPMacManager.GetIPMacList;
end;


/////////////////////////////////////

procedure TMainForm.ReadData(var Message: TMessage);
var
   buffer: Array [1..500] of byte;
   len: integer;
   flen: integer;
   Event: word;
   IP,Mac,GroupHostName,tmp: string;
   iPos,NameNum:integer;
begin
     flen:=sizeof(FSockAddrIn);
     FSockAddrIn.SIn_Port := htons(NBTPORT);
     Event := WSAGetSelectEvent(Message.LParam);
     if Event = FD_READ then
     begin
          len := recvfrom(FSocket, buffer, sizeof(buffer), 0, FSockAddrIn, flen);
          if len<> 0 then
          begin
          try
            IP:=inet_ntoa(FSockAddrIn.SIn_Addr);
            GetInfo(buffer,len,iPos,NameNum);
            Mac:=GetMac(buffer,iPos,NameNum);
            tmp:=Uppercase(IPMacManager.FindByIP(IP));
            if Pos(Mac,tmp)<=0 then
               IPMacManager.AddMac(IP,Mac);
            GroupHostName:=GetGroupHostName(buffer,iPos,NameNum);
            if(IP<>'') and (GroupHostName<>'') then
            IPMacManager.NameModify(Mac,IP,GroupHostName);
            LogStr(#13+'ScanThread ['+IP+'] = '+Mac+#13+'                                  '+GroupHostName);
            //LogStr('                                  '+GroupHostName);
            //LogStr('ScanThread ['+IP+'] = '+Mac);
          except
            On Ex:Exception do
               memo1.Lines.Insert(0,Ex.Message);
          end;


          end;
     end;
       application.ProcessMessages;

end;
procedure TMainForm.ScanIP_UDP(IP:string;b:array of byte);
begin
     FSockAddrIn.SIn_Addr.S_addr := inet_addr(pchar(IP));
     sendto(FSocket, b[0],50, 0, FSockAddrIn, sizeof(FSockAddrIn));
end;
procedure TMainForm.InitSocket;
var  TempWSAData: TWSAData;
begin
     // 初始化SOCKET
     if WSAStartup($101, TempWSAData)=1 then
        ;//showmessage('StartUp Error!');

     FSocket := Socket(AF_INET, SOCK_DGRAM, 0);
     if (FSocket = INVALID_SOCKET) then   //Socket创建失败
     begin
          //showmessage(inttostr(WSAGetLastError())+'  Socket创建失败');
          CloseSocket(FSocket);
     end;
     //本机SockAddr绑定
     Socketaddr.sin_family := AF_INET;
     Socketaddr.sin_addr.S_addr := INADDR_ANY;
     Socketaddr.sin_port := htons(UDPPORT);
     if Bind(FSocket, Socketaddr, sizeof(Socketaddr)) <> 0  then
       begin
         //showmessage('bind fail');
       end;
     WSAAsyncSelect(FSocket, self.Handle , WM_SOCK, FD_READ);
     //对方SockAddrIn设定
     FSockAddrIn.SIn_Family := AF_INET;
     FSockAddrIn.SIn_Port := htons(NBTPORT);
end;
procedure GetInfo(buffer: Array of byte;len:integer;var iPos:integer;var NameNum:integer);
var i: integer;
begin
  for i:=1 to len do
  begin
    if((buffer[i]=$21)and(buffer[i+1]=$00)and(buffer[i+2]=$01))
    then
    begin
      NameNum:=buffer[i+9];
      break;
    end;
  end;
  iPos:=i+10;
end;
Function GetGroupHostName(buffer: Array of byte;pos:integer;name_num:integer):string;
var
    str:string;
    i,j: integer;
    GROUPStr:string;
    UNIQUEStr:string;
begin

  result:='';
  if name_num=0 then exit;
  GROUPStr:='';
  UNIQUEStr:='';   
  str:='';
  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(' ');
        str:=str+char(buffer[i+j]);
      end;
    if (buffer[i+16] and $80)=$80 then
    begin
      GROUPStr:=str;
    end
    else
    begin
      UNIQUEStr:=str;
    end;
    str:='';
    end;
  end;
  result:='['+Trim(UNIQUEStr)+'/'+Trim(GROUPStr)+']';
end;
Function GetMac(buffer: Array of byte;pos:integer;name_num:integer):string;
var  i: integer;
begin

  result:='';
  if (name_num=0)  or (high(buffer)<0)then exit;
  for i:=0 to 5 do
  begin
    result:=result+format('%.2x-',[buffer[i+pos+18*name_num]]);
  end;
  delete(result,length(result),1);

end;
end.

⌨️ 快捷键说明

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