Delphi - 多线程端口检查器

时间:2015-10-08 13:04:29

标签: multithreading delphi

我正在尝试将单线程应用程序转换为多线程应用程序。

基本上,我想每隔10秒同时检查50个端口,看看它们是在线还是离线。

我正在使用列表框加载所有ip和端口(127.0.0.1:50008),我解析了ip和端口号并使用此函数检查它:

uses idTCPclient;

function IsPortActive(AHost : string; APort : string): boolean;
var
  IdTCPClient : TIdTCPClient;
begin
  Result := False;
  try
    IdTCPClient := TIdTCPClient.Create(nil);
    try
      IdTCPClient.Host := AHost;
      IdTCPClient.Port := strtoint(APort);
      IdTCPClient.ConnectTimeout:=50;
      IdTCPClient.Connect;
      Result := True;
    finally
      IdTCPClient.Free;
    end;
  except
    //Ignore exceptions
  end;
end;

以下是开始检查端口并相应地发出结果信号的过程:

procedure TForm2.Button1Click(Sender: TObject);
begin
  if isportactive('127.0.0.1','50008') then
    listbox_online.items.add(ip+''+port)
  else
    listbox_offline.items.add(ip+''+port);
end;

有人可以指导我如何将其转换为可以接受IP和端口作为参数的线程吗?

1 个答案:

答案 0 :(得分:3)

编写线程的一种方法就是这个。

我没有添加任何额外的TNotifyEvent方法,因为您可以在线程的OnTerminate事件中查找所需的属性。

type
  THostChecker = class(TThread)
    strict private
      FIdTCPClient: TIdTCPClient;
      FHost: string;
      FPort: Integer;
      FConnectTimeout: Integer;
      FIsPortActive: Boolean;
    protected
      procedure Execute; override;
    public
      constructor Create(const AHost: string; APort: Integer; AConnectTimeout: Integer = 50; CreateSuspended: Boolean = False);
      property IsPortActive: Boolean read FIsPortActive;
      property Host: string read FHost;
      property Port: Integer read FPort;
      destructor Destroy; override;
  end;

implementation

{ THostChecker}

constructor THostChecker.Create(const AHost: string; APort: Integer; AConnectTimeout: Integer; CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);
  FHost := AHost;
  FPort := APort;
  FConnectTimeout := AConnectTimeout;
  FIdTCPClient := TIdTCPClient.Create(nil);
  FIsPortActive := False;
end;

destructor THostChecker.Destroy;
begin
  FIdTCPClient.Free;
  inherited;
end;

procedure THostChecker.Execute;
begin
  inherited;
  with FIdTCPClient do begin
    Host := FHost;
    Port := FPort;
    ConnectTimeout := FConnectTimeout;
    Connect;
    FIsPortActive := True;
  end;
end;

以下是相关部分的表格:

procedure TForm4.Button1Click(Sender: TObject);
const
  hosts: array [0..6] of string = ('google.com', 'stackoverflow.com', 'youtube.com', 'foo.org', 'null.org', 'porn.com', 'microsoft.com');
var
 i: Integer;
begin
  for i:=Low(hosts) to High(hosts) do
    with THostChecker.Create(hosts[i], 80, 50, False) do begin
      OnTerminate := HostCheckerTerminate;
      FreeOnTerminate := True;
    end;
end;

procedure TForm4.HostCheckerTerminate(Sender: TObject);
var
  hostChecker: THostChecker;
  ex: Exception;
  hostAndPort: string;
begin
  hostChecker := THostChecker(Sender);

  ex := Exception(hostChecker.FatalException);
  if Assigned(ex) then
    //do something useful here or don't evaluate ex at all

  hostAndPort := Format('%s:%d', [hostChecker.Host, hostChecker.Port]);

  if hostChecker.IsPortActive then
    listbox_online.items.add(hostAndPort)
  else
    listbox_offline.items.add(hostAndPort);
end;

属性FreeOnTerminate设置为True,以避免为线程本身调用Free

在线程的OnTerminate事件中执行的代码已在调用线程中同步。

线程不会在调用阶段引发异常,但您可以检查Execute方法中是否发生了异常,评估FatalException事件中的OnTerminate属性。