📄 nbtstat.pas
字号:
{
(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 + -