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

📄 nbtstat.pas

📁 最好的局域网搜索软件
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{
  (c)2001 zw84611
  this unit do the samce thing as dos command "nbtstat -a ip".
  
  This is not a vcl component, it's just a unit, needn't install.
}
unit Nbtstat;

interface

uses
  Windows, Messages, SysUtils, Classes, Controls, Dialogs, WinSock, ComCtrls, Forms;

const
  WM_SOCK = WM_USER + 1;     //自定义windows消息
  //UDPPORT = 6767;            //设定UDP端口号
  NBTPORT = 137;             //NAME_SERVICE_UDP_PORT   137 (decimal)  (RFC1002)

type
  TNbt = class(TComponent)
  private
    s: TSocket;
    addr: TSockAddr;
    FSockAddrIn : TSockAddrIn;  //利用消息实时获知UDP消息
    FHandle: HWnd;              //非可视构件消息处理使用
    procedure ReadData(var Message: TMessage); //message WM_SOCK;
    procedure RecvNbMsg(buffer: array of byte;len:integer;IP:string);
    procedure SendData(b:array of byte;IP:string);
  public
    wait_time:            integer;
    StartIP, EndIP: string;
    StatusString: string;
    MyListView: TListView;
    OnEndEvent: TNotifyEvent;
    OnSendEvent: TNotifyEvent;
    OnAddNodeEvent: TNotifyEvent;
    //RootTreeNode: TTreeNode;
    
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Start;
    procedure Stop;
    procedure Pause;
    procedure Restart;

  end;

  TSendDataThread=class(TThread)
  private
    IP, IP1, IP2: string;
  protected
    procedure Execute; override;
    procedure GetIP;
    procedure Send;
    procedure OnExit;
  end;

var
  Nbt: TNbt;
  B1,B2:                array [0..3]of byte;
  SendDataThread:       TSendDataThread;
  WAIT_ACK_EVENT:       Thandle;
  exit_nbt_thread:          boolean;

implementation
//uses FmxUtils; // IsLegalIP
{
function IsLegalIP(IP:string):boolean;
begin

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

end;
}

{
procedure GetAddrByte(IP:string;var B:array of byte);
var i,j:integer;
    s:string;
begin

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

end;
}

procedure TSendDataThread.Send;
{
  RFC1002: " PROTOCOL STANDARD FOR A NetBIOS SERVICE ON A TCP/UDP TRANSPORT:
           DETAILED SPECIFICATIONS "
           
  4.2.17.  NODE STATUS REQUEST

                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         NAME_TRN_ID           |0|  0x0  |0|0|0|0|0 0|B|  0x0  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          0x0001               |           0x0000              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          0x0000               |           0x0000              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   /                         QUESTION_NAME                         /
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         NBSTAT (0x0021)       |        IN (0x0001)            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+	
}
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);
begin

    Nbt.StatusString := '正在测试:' + IP;
    if assigned(Nbt.OnSendEvent) then Nbt.OnSendEvent(nil);
    Nbt.SendData(NbtstatPacket, IP);

end;

procedure TSendDataThread.GetIP;
begin

  IP1 := Nbt.StartIP;
  IP2 := Nbt.EndIP;

end;

procedure TSendDataThread.OnExit;
begin

  if assigned(Nbt.OnEndEvent) then Nbt.OnEndEvent(nil);

end;

procedure TSendDataThread.Execute;
var
  nIP1, nIP2, i: dword;
begin

  Synchronize(GetIP);
  
  {if (not IsLegalIP(IP1))or(not IsLegalIP(IP2))  then
  begin
    ShowMessage('Illegal IP address!');
    exit;
  end; }

  //GetAddrByte(IP,B1);
  //GetAddrByte(IP2,B2);
  nIP1 := ntohl(inet_addr(pchar(IP1)));
  nIP2 := ntohl(inet_addr(pchar(IP2)));

  for i := nIP1 to nIP2 do
  begin
    if exit_nbt_thread then
    begin
      Synchronize(OnExit);
      exit;
    end;

    //去掉x.x.x.0或x.x.x.255的地址。
    if (((i - 255) mod 256)=0)or((i mod 256)=0) then continue;

    IP := inet_ntoa(in_addr(htonl(i)));
    Synchronize(Send);

    WaitForSingleObject(WAIT_ACK_EVENT,Nbt.wait_time);
    ResetEvent(WAIT_ACK_EVENT);
  end;
{
  repeat

    if exit_thread then
    begin
      Synchronize(OnExit);
      exit;
    end;
    IP:=format('%d.%d.%d.%d',[B1[0],B1[1],B1[2],B1[3]]);
    Synchronize(Send);

    WaitForSingleObject(WAIT_ACK_EVENT,Nbt.wait_time);
     ResetEvent(WAIT_ACK_EVENT);

    if(B1[2]<=B2[2]) then
    begin
       if(B1[3]<B2[3]) then inc(B1[3])
       else if((B1[2]<B2[2]) and (B1[3]<255))then inc(B1[3])
       else if((B1[2]<B2[2]) and (B1[3]=255)) then
       begin
               B1[3]:=1;
               inc(B1[2]);
       end;
    end
    else break;
    if((B1[3]>=B2[3]) and (B1[2]>=B2[2])) then break;

  until ((B1[2]=255));// or (B1[3]=255));
}

  Synchronize(OnExit);

end;

constructor TNbt.Create(AOwner: TComponent);
var
   TempWSAData: TWSAData;
   //optval: integer;
begin

     inherited Create(AOwner);
     FHandle := AllocateHWnd(ReadData);  //attention here.


     // 初始化SOCKET
     if WSAStartup($101, TempWSAData)=1 then
        showmessage('StartUp Error!');

     s := Socket(AF_INET, SOCK_DGRAM, 0);
     if (s = INVALID_SOCKET) then   //Socket创建失败
     begin
          ShowMessage(inttostr(WSAGetLastError())+'  Socket创建失败');
          CloseSocket(s);
     end;
     //本机SockAddr绑定
     addr.sin_family := AF_INET;
     addr.sin_addr.S_addr := INADDR_ANY;
     //addr.sin_port := htons(UDPPORT);
     if Bind(s, addr, sizeof(addr)) <> 0  then
       begin
         showmessage('bind fail');
       end;
     WSAAsyncSelect(s, FHandle , WM_SOCK, FD_READ);
     //对方SockAddrIn设定
     FSockAddrIn.SIn_Family := AF_INET;
     FSockAddrIn.SIn_Port := htons(NBTPORT);

     WAIT_ACK_EVENT:=CreateEvent(nil,true,false,pchar('WAIT_ACK'));
     //ResetEvent(WAIT_ACK_EVENT);
     wait_time:=100;

end;

destructor TNbt.Destroy;
begin

  CloseSocket(s);
  WSACleanup(); 
  DeallocateHWnd(FHandle);
  inherited Destroy; 

end;

⌨️ 快捷键说明

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