线程在网络编程应用中遇到的问题!!大家一起研究研究! (30分)

  • 主题发起人 主题发起人 sailorhdx
  • 开始时间 开始时间
S

sailorhdx

Unregistered / Unconfirmed
GUEST, unregistred user!
线程类:
unit T_GetComputer;
interface
uses
Windows, SysUtils, Classes, Winsock, Dialogs;
type
TGetMacThread = class(TThread)
private
FIP:string;
FMacAddr: string;
//物理MAC地址
FHostName: string;
//主机名
protected
function GetMacByIP(FIPAddr: string): string;
procedure Execute;
override;
procedure SynchronizeIsMac;
function IPToName(IP: string): string;
public
constructor Create(const Para_IP: string);
virtual;
end;
const
INADDR_NONE = $FFFFFFFF;
implementation
uses Unit1;
{获取客户机Mac地址等信息}
function inet_addr(const cp: PChar): DWord;
stdcall;
external 'WS2_32.DLL'
name 'inet_addr';
function SendARP(const DestIP: DWord;
const SrcIP: DWord;
const pMacAddr: Pointer;
const PhyAddrLen: PULONG): DWord;
stdcall;
external 'IPHLPAPI.dll' name 'SendARP';

function TGetMacThread.GetMacByIP(FIPAddr: string): string;
var
dwResult: DWord;
ulIPAddr: DWord;
ulMacAddr: array[0..5] of Byte;
ulAddrLen: ULONG;
begin
ulIPAddr := INet_Addr(PChar(FIPAddr));
if ulIPAddr = INADDR_NONE then
exit;
ulAddrLen := 6;
dwResult := SendARP(ulIPAddr, 0, @ulMacAddr, @ulAddrLen);
if dwResult = 0 then
result := (IntToHex(ulMacAddr[0], 2) + ':' +
IntToHex(ulMacAddr[1], 2) + ':' +
IntToHex(ulMacAddr[2], 2) + ':' +
IntToHex(ulMacAddr[3], 2) + ':' +
IntToHex(ulMacAddr[4], 2) + ':' +
IntToHex(ulMacAddr[5], 2))
else
result := '';
end;

function TGetMacThread.IPToName(IP: string): string;
var
WSAData: TWSAData;
p: PHostEnt;
InetAddr: DWord;
begin
WSAStartup(2, WSAData);
InetAddr := inet_addr(PChar(IP));
try
p := GetHostByAddr(@InetAddr, Length(IP), PF_Inet);
if not (p = nil) then
result := p^.h_name
else
result := '';
except
result := '';
end;
end;

constructor TGetMacThread.Create(const Para_IP: string);
begin
FIP := Para_IP;
FMacAddr := '';
FHostName := '';
inherited Create(False);
FreeOnTerminate := True;
end;

procedure TGetMacThread.Execute;
begin
FMacAddr := GetMacByIP(FIP);
if FMacAddr > '' then
FHostName := IPToName(FIP);
if ((FMacAddr > '') and (FHostName > '')) then
Synchronize(SynchronizeIsMac)
end;

procedure TGetMacThread.SynchronizeIsMac;
begin
Form1.Memo1.Lines.Add(FIP + ' ' + FMacAddr + ' ' + FHostName);
end;

end.

主窗体:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, T_GetComputer;
type
TForm1 = class(TForm)
Edit1: TEdit;
Memo1: TMemo;
Button1: TButton;
Timer1: TTimer;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
// Edit1.Text := IntToStr(StrToInt(Copy('1234560000025', 7, 7)));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if Timer1.Enabled = True then
Timer1.Enabled := False
else
Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
Tmp_TGetMacThread: TGetMacThread;
i: Integer;
begin
Edit1.Text := DateTimeToStr(Now);
Memo1.Clear;
for I := 1 to 254do
// Iterate
begin
Tmp_TGetMacThread := TGetMacThread.Create('192.168.0.' + IntToStr(i));
end;
// for
end;

end.

在Timer实践中定时循环检测网段内的IP及其对应的Mac地址和主机名称!
运行一段时间后会出现 "存储空间不足,无法执行命令" 的错误信息!
 
今天一天就遇到两个这样的问题,怎么大家都喜欢把创建线程放
定时器里。还成百上千的创建。一个进程里能创建的线程是有限制的。
还是把 Timer 的Interval设得大点吧.
 
可是有些是不能避免的需要这样短间隔的循环的,有没有其他的好办法呢?
 
应该线程的数量加以限制,对进程中当前的线程数量用个变量存储。
创建的时候加1,线程结束的时候可以考虑发条消息给主窗口,将线程数减一.
更好的设计方法是把循环体放在线程中.
 
timer的间隔时间太小了?
在进入TIMER时,加上timer1.enabled := false;
返回前 加上timer1.enabled := true;
线程太多了,很快就会用完内存的。
 
在可以不用线程的地方,为什么要用线程?
还要用定时器加线程,这是自己耍自己。
做个有timeout的查询实际得多
 
多人接受答案了。
 

Similar threads

I
回复
0
查看
597
import
I
I
回复
0
查看
836
import
I
I
回复
0
查看
1K
import
I
后退
顶部