📄 umainform.~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 + -