www.pudn.com > cvery_7181819113.rar > U_FrmSearchNetIp.~pas


{局域网IP搜索} 
unit U_FrmSearchNetIp; 
 
interface 
 
uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, 
  WinSock,Forms, Dialogs, RXSpin, StdCtrls, ExtCtrls, Buttons, RXSplit, 
  Grids, ComCtrls, RxRichEd; 
 
const 
  WM_SOCK = WM_USER + 1;     {自定义windows消息} 
  NBTPORT =  137;   	     {向对方的137端口发数据包(UDP包)} 
 
Type 
  TTGroupNet=record {网络标识} 
      IP:string; 
      ComputerName:string; 
      ComputerDes:string; 
      NetGroup:string; 
      NetMacCode:string; 
  end; 
type 
  TFrmSearchNetIp = class(TForm) 
    Panel2: TPanel; 
    Panel1: TPanel; 
    Label1: TLabel; 
    Label2: TLabel; 
    Label3: TLabel; 
    EdNetIP1: TEdit; 
    EdNetIP2: TEdit; 
    RxSEdDelay: TRxSpinEdit; 
    Panel3: TPanel; 
    Panel4: TPanel; 
    PageControl1: TPageControl; 
    TabSheet1: TTabSheet; 
    SgDispNetIP: TStringGrid; 
    TabSheet2: TTabSheet; 
    Panel5: TPanel; 
    Panel6: TPanel; 
    SBrnScanNetIP: TSpeedButton; 
    SBtnStopScan: TSpeedButton; 
    RxRedDispinf: TRxRichEdit; 
    LabIP: TLabel; 
    LabStartTime: TLabel; 
    LabEndTime: TLabel; 
    LabTime: TLabel; 
    Label4: TLabel; 
    TabSheet3: TTabSheet; 
    RxRichEdit1: TRxRichEdit; 
    procedure FormCreate(Sender: TObject); 
    procedure FormClose(Sender: TObject; var Action: TCloseAction); 
    procedure SBtnStopScanClick(Sender: TObject); 
    procedure SBrnScanNetIPClick(Sender: TObject); 
    procedure SgDispNetIPSelectCell(Sender: TObject; ACol, ARow: Integer; 
      var CanSelect: Boolean); 
    procedure SgDispNetIPDblClick(Sender: TObject); 
  private 
    { Private declarations } 
    procedure ReadData(var Message: TMessage); message WM_SOCK;  {消息接送} 
    Procedure ClearGrid(); 
    Procedure MakeGrid(Const IntIndex:integer=3);{排序} 
 
  public 
    { Public declarations } 
  end; 
 
{*******************************************************} 
  TComread=class(TThread) {通讯线程} 
  private 
  public 
   Tagg:integer; 
  protected 
    procedure Execute; override; 
  end; 
  {始化SOCKET} 
  Procedure WinSockInital(Handle: HWnd); 
  {关闭SOCKET} 
  Procedure WinSockClose(); 
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 
  FrmSearchNetIp: TFrmSearchNetIp; 
 
  TF_stop:boolean;  {停止} 
  TempWSAData: TWSAData; 
  sockfd:TSocket;  	  {Integer socket句柄} 
  WAIT_ACK_EVENT:Thandle; {LongWord  句柄|} 
  FSockAddrIn : TSockAddrIn; 
 
  IP_count,ComputerIP:integer; 
  IP_end:     Dword; 
  StartTickCount:DWORD ; {计数器} 
  StopTickCount: DWORD ; 
 
  TGroupNet:array of TTGroupNet;{网络信息寄存} 
  IntGridCol:integer; 
   
implementation 
 
{$R *.DFM} 
 
procedure TFrmSearchNetIp.FormCreate(Sender: TObject); 
begin 
    IntGridCol:=0; 
    {TRxRichEdit 去除64K的限制} 
    RxRedDispinf.MaxLength := High(Integer) - 1024; 
    {Grid清除 ClearGrid} 
    ClearGrid; 
end; 
procedure TFrmSearchNetIp.FormClose(Sender: TObject; 
  var Action: TCloseAction); 
begin 
  TF_stop:=True; 
  setlength(TGroupNet,0); 
  {关闭SOCKET} 
  WinSockClose(); 
end; 
{停止扫描} 
procedure TFrmSearchNetIp.SBtnStopScanClick(Sender: TObject); 
begin 
 TF_stop:=True; 
end; 
 
 
{****************** SOCKET通讯  *****************} 
{始化SOCKET} 
Procedure WinSockInital(Handle: HWnd); 
begin 
     { 1 初始化SOCKET} 
     TF_stop:=false; 
     if WSAStartup(2, TempWSAData)=1 then 
     begin 
       showmessage('Socket初始化出错'); 
       exit 
     end; 
     {若是用UDP通信,则用} 
     sockfd:=Socket(AF_INET,SOCK_DGRAM,0); 
 
     FSockAddrIn.SIn_Family := AF_INET; 
     FSockAddrIn.SIn_Port := htons(NBTPORT);  {137端口} 
 
    {Socket的信息传递--》From.Handle 窗体, FD_READ 在读就绪的时候, WM_SOCK 自定义消息号} 
     WSAAsyncSelect(sockfd, Handle , WM_SOCK, FD_READ); 
    {创建事件} 
     WAIT_ACK_EVENT:=CreateEvent(nil,true,false,pchar('WAIT_ACK') ); 
     ResetEvent(WAIT_ACK_EVENT); 
end; 
{关闭SOCKET} 
Procedure WinSockClose(); 
begin 
   TF_stop:=True; 
   CloseSocket(sockfd); {closesocket函数用来关闭一个描述符为sockfd套接字} 
   WSACleanup; 
   sleep(2); 
end; 
{****************** SOCKET通讯  *****************} 
{扫描开始} 
procedure TFrmSearchNetIp.SBrnScanNetIPClick(Sender: TObject); 
var 
  DWx1,Dwx:Dword; 
  IP,Str_Ip:string; 
  Tcomr:TComread; 
begin 
   RxRichEdit1.text:=''; 
   Setlength(TGroupNet,0); 
   {始化SOCKET} 
   WinSockInital(FrmSearchNetIp.Handle); 
 
   {清除Grid} 
   ClearGrid; 
   TF_stop:=false; 
   IP:=trim(EdNetIP1.text); 
   RxRedDispinf.Text :=''; 
   label4.Caption:='IP个数:';  
   LabIP.caption:=''; 
   LabStartTime.caption:='开始时间:'; 
   LabEndTime.caption:='结束时间:'; 
   LabTime.caption:='扫描用时:'; 
   if Longword(inet_addr(pchar(IP)))=INADDR_NONE then 
   begin 
      Messagebox(Application.handle,pchar(IP + ' TP 出错'),'警告',MB_OK+MB_ICONERROR); 
      exit; 
   end; 
   IP:=trim(EdNetIP2.text); 
   if Longword(inet_addr(pchar(IP)))=INADDR_NONE then 
   begin 
      Messagebox(Application.handle,pchar(IP + ' TP 出错'),'警告',MB_OK+MB_ICONERROR); 
      exit; 
   end; 
    IP:=trim(EdNetIP1.text); 
    ComputerIP:=inet_addr(PChar(IP)) ;  // 192.168.0.1 ===>01 00 A8 C0 
    str_ip:=inttohex(ComputerIP,8);    //01 00 A8 C0 
    str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2);   //==> C0 A8 00 01 
    DWx:=strtoint('$'+str_ip); {转换成为一个长整形数} 
 
    str_ip:=inttohex(ComputerIP,8); 
    str_ip:=inttostr(strtoint('$' + copy(str_ip,7,2))) 
                +'.' + inttostr(strtoint('$' + copy(str_ip,5,2))) 
                +'.' + inttostr(strtoint('$' + copy(str_ip,3,2))) 
                +'.' + inttostr(strtoint('$' + copy(str_ip,1,2))); 
    EdNetIP1.text:=str_ip;  {允许输入 一个数值表示IP} 
 
    IP:=trim(EdNetIP2.text); 
    ComputerIP:=inet_addr(PChar(IP)) ;  // 192.168.0.1 ===>01 00 A8 C0 
    str_ip:=inttohex(ComputerIP,8);    //01 00 A8 C0 
    str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2);   //==> C0 A8 00 01 
    DWx1:=strtoint('$'+str_ip);   {转换成为一个长整形数} 
 
    str_ip:=inttohex(ComputerIP,8); 
    str_ip:=inttostr(strtoint('$' + copy(str_ip,7,2))) 
               +'.' + inttostr(strtoint('$' + copy(str_ip,5,2))) 
               +'.' + inttostr(strtoint('$' + copy(str_ip,3,2))) 
               +'.' + inttostr(strtoint('$' + copy(str_ip,1,2))); 
    EdNetIP2.text:=str_ip;  {允许输入 一个数值表示IP} 
 
     if DWx1>Dwx then 
     begin 
        IP_count:=DWx1-Dwx; 
        ComputerIP:=inet_addr(PChar(trim(EdNetIP1.text))); 
        IP_end:=DWx1; 
        label1.caption:='-->>'; 
     end 
     else begin 
        IP_count:=DWx-Dwx1; 
        ComputerIP:=inet_addr(PChar(trim(EdNetIP2.text))); 
        IP_end:=DWx; 
        label1.caption:='<<--'; 
     end; 
 
    SBrnScanNetIP.Enabled :=false;  {屏蔽按键} 
    Tcomr:=TComread.Create(True); 
    StartTickCount:=GetTickCount; 
    LabStartTime.caption:='开始时间:' + FloatToStr(StartTickCount); 
    Tcomr.Resume ;  {开始线程} 
end; 
{ TComread } 
{通讯线程} 
procedure TComread.Execute; 
var 
   str_ip:string; 
   IP_now:Dword; 
   Procedure MakeEnd(); 
   begin 
     FrmSearchNetIp.SBrnScanNetIP.Enabled :=True; 
     StopTickCount:=GetTickCount; 
     FrmSearchNetIp.LabEndTime.caption:='结束时间:' +FloatToStr(StopTickCount); 
     FrmSearchNetIp.LabTime.caption:='扫描用时:' +FloatToStr(StopTickCount-startTickCount)+' mS'; 
     FrmSearchNetIp.label4.Caption:='IP个数:'+ inttostr(FrmSearchNetIp.SgDispNetIP.RowCount-1); 
     FrmSearchNetIp.MakeGrid(3); 
 {排序 
 'TP地址'0  '计算机名称'1  '计算机描述' 2 
 '网络组'3  '网卡MAC码'4 
  MakeGrid(const IntIndex: integer=3);} 
   end; 
begin 
 
  with FrmSearchNetIp do 
  begin 
     str_ip:=inttohex(ComputerIP,8);    //01 00 A8 C0 
     str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2);   //==> C0 A8 00 01 
     IP_now:=strtoint('$'+str_ip); 
 
      while IP_end>=IP_now do         ////IP_end==> C0 A8 00 01 
      begin 
         if TF_stop=True then 
         begin 
          MakeEnd(); 
          {关闭SOCKET} 
          WinSockClose(); 
          exit; 
         end; 
         str_ip:=inttohex(ComputerIP,8); 
         str_ip:=inttostr(strtoint('$' + copy(str_ip,7,2))) 
                +'.' + inttostr(strtoint('$' + copy(str_ip,5,2))) 
                +'.' + inttostr(strtoint('$' + copy(str_ip,3,2))) 
                +'.' + inttostr(strtoint('$' + copy(str_ip,1,2))); 
         LabIP.caption:=str_ip;  {目前扫描的IP} 
 
         FSockAddrIn.SIn_Addr.S_addr := ComputerIP;//inet_addr(pchar(IP)); 
         str_ip:=inttohex(ComputerIP,8);    //01 00 A8 C0 
         str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2);   //==> C0 A8 00 01 
         str_ip:=inttohex( strtoint(('$' + str_ip))+1,8);      //==> 加一C0 A8 00 02 
         IP_now:=strtoint('$'+str_ip); 
         str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2);  //==>02 00 A8 C0 
         ComputerIP:=strtoint('$'+str_ip); 
         sendto(sockfd, NbtstatPacket,50, 0, FSockAddrIn, sizeof(FSockAddrIn)); 
         //发送数据后 
         waitforsingleobject(WAIT_ACK_EVENT,trunc(  RxSEdDelay.Value)); // 等待事件变成有信号 
         ResetEvent(WAIT_ACK_EVENT);   		  // 设为没有信号 
      end; 
      MakeEnd(); 
  end; 
 {关闭SOCKET} 
  WinSockClose(); 
end; 
 
 
{ TFrmSearchNetIp } 
{消息接送} 
procedure TFrmSearchNetIp.ReadData(var Message: TMessage); 
var 
   Buffer: Array [1..500] of byte; 
   flen,len,i,j,pos,name_num: integer; 
   Event: word; 
   IP:string; 
   str_tp,str:string; 
   str_list_IP,str_list_name,str_list_disp,str_list_group,str_list_MAC:string; 
   StrTp:string; 
begin 
     flen:=sizeof(FSockAddrIn); 
     Event := WSAGetSelectEvent(Message.LParam); 
     if Event = FD_READ then 
     begin 
          len := recvfrom(sockfd, 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)]); 
              str_list_IP:=IP; 
              //数据分析 
              name_num:=0; 
              str_tp:=''; 
	      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; 
              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 
                      if buffer[i+15]=$0 then str_list_GROUP:=trim(str);  //网络组 
	              str:=str+format('<%x>',[buffer[i+15]]); 
		      str:=str+''; 
		   end 
		   else begin 
  	                if buffer[i+15]=$20 then str_list_name:=trim(str) //计算机名 
  		        else 
		           if buffer[i+15]=$3 then str_list_disp:=trim(str);//计算机说明 
		        str:=str+format('<%x>',[buffer[i+15]]); 
		        str:=str+''; 
		   end; 
		    str_tp:=str_tp + str +#13+#10; 
		    str:=''; 
		 end; 
	      end; 
	      for i:=0 to 5 do 
	      begin 
	          str:=str+format('%.2x.',[buffer[i+pos+18*name_num]]); 
	      end; 
	      delete(str,length(str),1); 
              str_list_MAC:=trim(str); //网卡的MAC码 
	      str:='MAC:     '+str; 
              str_tp:=str_tp + str + #13+#10; 
              {网络信息} 
              RxRedDispinf.Text :=RxRedDispinf.Text +IP +  #13+#10+  str_tp+ #13+#10; 
              {Grid} 
              I:=SgDispNetIP.RowCount; 
              if I=2 then 
              begin 
                 if trim(SgDispNetIP.Cells[0,1])<>'' then 
                 begin 
                    Inc(i); 
                    SgDispNetIP.RowCount:=I; 
                 end; 
              end 
              else begin 
                   Inc(i); 
                   SgDispNetIP.RowCount:=I; 
              end; 
              Dec(i); 
              SgDispNetIP.Cells[0,i]:=str_list_IP;//'TP地址' 
              SgDispNetIP.Cells[1,i]:=str_list_name;//'计算机名称' 
              SgDispNetIP.Cells[2,i]:=str_list_disp;//'计算机描述' 
              SgDispNetIP.Cells[3,i]:=str_list_GROUP;//'网络组' 
              SgDispNetIP.Cells[4,i]:=str_list_MAC;//'网卡MAC码' 
              { 
              RichEdit1.Text :=RichEdit1.Text + str_list_IP + ' ' + str_list_name + '  ' + 
              str_list_disp + '  ' + str_list_GROUP +'    '  + str_list_MAC+ #13+#10 
              } 
              setlength(TGroupNet,high(TGroupNet)+2); 
              TGroupNet[high(TGroupNet)].IP:=str_list_IP;//'TP地址' 
              TGroupNet[high(TGroupNet)].ComputerName :=str_list_name;//'计算机名称' 
              TGroupNet[high(TGroupNet)].ComputerDes:=str_list_disp;//'计算机描述' 
              TGroupNet[high(TGroupNet)].NetGroup:=str_list_GROUP;//'网络组' 
              TGroupNet[high(TGroupNet)].NetMacCode :=str_list_MAC;//'网卡MAC码' 
 
              StrTp:=str_list_IP + '   ' +str_list_name+ '   ' + 
                str_list_disp + '   ' + str_list_GROUP + '   ' + 
                str_list_MAC; 
              RxRichEdit1.Lines.Add(StrTp); 
          end; 
          SetEvent(WAIT_ACK_EVENT);//有信号 
     end; 
end; 
{Grid清除 ClearGrid} 
procedure TFrmSearchNetIp.ClearGrid; 
begin 
   SgDispNetIP.RowCount:=2; 
   SgDispNetIP.Rows[1].Text:=''; 
   SgDispNetIP.Cells[0,0]:='TP地址' ; 
   SgDispNetIP.Cells[1,0]:='计算机名称' ; 
   SgDispNetIP.Cells[2,0]:='计算机描述' ; 
   SgDispNetIP.Cells[3,0]:='网络组' ; 
   SgDispNetIP.Cells[4,0]:='网卡MAC码' ; 
end; 
 
  
{排序} 
{ 
'TP地址'0 
'计算机名称'1 
'计算机描述' 2 
'网络组'3 
'网卡MAC码'4 
} 
procedure TFrmSearchNetIp.MakeGrid(const IntIndex: integer=3); 
Var 
  X,XCount:integer; 
  GroupNet:TtGroupNet; 
  IntMin:integer; 
    Procedure GetMinTGroupNet();{获取最小TGroupNet} 
    Var 
       Y:integer; 
       NetMinIP, NetIP:integer; 
       DWxMin,DWx:Dword; 
       str_ip:string;        
    begin 
       GroupNet:= tGroupNet[x] ; 
       IntMin:=x; 
       for Y:=x+1 to XCount do 
       begin 
         case Intindex of 
           0:begin //'TP地址'0 
 
                NetMinIP:=inet_addr(PChar(GroupNet.IP)) ;  // 192.168.0.1 ===>01 00 A8 C0 
                str_ip:=inttohex(NetMinIP,8);    //01 00 A8 C0 
                str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2);   //==> C0 A8 00 01 
                DWxMin:=strtoint('$'+str_ip);   {转换成为一个长整形数} 
 
                NetIP:=inet_addr(PChar(tGroupNet[y].IP)) ;  // 192.168.0.1 ===>01 00 A8 C0 
                str_ip:=inttohex(NetIP,8);    //01 00 A8 C0 
                str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2);   //==> C0 A8 00 01 
                DWx:=strtoint('$'+str_ip);   {转换成为一个长整形数} 
 
                if DWxMin> DWx then 
//                if inet_addr(PChar(GroupNet.IP))> inet_addr(PChar(tGroupNet[y].IP)) then 
                begin 
                  IntMin:=y; 
                  GroupNet:=tGroupNet[IntMin]; 
                end; 
             end; 
           1:begin //'计算机名称'1 
                if GroupNet.ComputerName > tGroupNet[y].ComputerName then 
                begin 
                  IntMin:=y; 
                  GroupNet:=tGroupNet[IntMin]; 
                end; 
             end; 
           2:begin //'计算机描述' 2 
                if GroupNet.ComputerDes > tGroupNet[y].ComputerDes then 
                begin 
                  IntMin:=y; 
                  GroupNet:=tGroupNet[IntMin]; 
                end; 
             end; 
           3:begin //'网络组'3 
                if GroupNet.NetGroup > tGroupNet[y].NetGroup then 
                begin 
                  IntMin:=y; 
                  GroupNet:=tGroupNet[IntMin]; 
                end; 
             end; 
           4:begin //'网卡MAC码'4 
                if GroupNet.NetMacCode > tGroupNet[y].NetMacCode then 
                begin 
                  IntMin:=y; 
                  GroupNet:=tGroupNet[IntMin]; 
                end; 
             end; 
         end;{case} 
       end;{For} 
    end; 
    Procedure MakeGrid();{重写Grid} 
    Var 
      Y:integer; 
      StrTp:string; 
    begin 
       SgDispNetIP.RowCount:=Xcount+2; 
       RxRichEdit1.Text :=''; 
       StrTp:=''; 
       For y:=0 to Xcount do 
       begin 
         SgDispNetIP.Cells[0,Y+1]:=TGroupNet[y].IP;//'TP地址' ; 
         SgDispNetIP.Cells[1,Y+1]:=tGroupNet[y].ComputerName;//'计算机名称' ; 
         SgDispNetIP.Cells[2,Y+1]:=tGroupNet[y].ComputerDes;//'计算机描述' ; 
         SgDispNetIP.Cells[3,Y+1]:=tGroupNet[y].NetGroup;//'网络组' ; 
         SgDispNetIP.Cells[4,Y+1]:=tGroupNet[y].NetMacCode;//'网卡MAC码' ; 
         StrTp:=TGroupNet[y].IP + '   ' +tGroupNet[y].ComputerName+ '   ' + 
                tGroupNet[y].ComputerDes + '   ' + tGroupNet[y].NetGroup + '   ' + 
                tGroupNet[y].NetMacCode; 
         RxRichEdit1.Lines.Add(StrTp); 
       end;{for} 
    end; 
begin 
    XCount:=high(TGroupNet); 
    if XCount<0 then exit; 
    {清除Grid} 
    ClearGrid; 
    for x:=0 to XCount do 
    begin 
        GetMinTGroupNet(); 
        if x<>IntMin then 
        begin 
           GroupNet:=TGroupNet[x]; 
           TGroupNet[x]:=TGroupNet[IntMin]; 
           TGroupNet[IntMin]:=GroupNet; 
        end; 
    end;{for} 
    MakeGrid();{重写Grid} 
end; 
 
procedure TFrmSearchNetIp.SgDispNetIPSelectCell(Sender: TObject; ACol, 
  ARow: Integer; var CanSelect: Boolean); 
begin 
    IntGridCol:=ACol; 
end; 
 
procedure TFrmSearchNetIp.SgDispNetIPDblClick(Sender: TObject); 
begin 
   MakeGrid(IntGridCol); 
end; 
 
end.