Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Сканер портов

2.2K
25 апреля 2010 года
S@tana
53 / / 15.10.2009
Написал тут простенький сканер портов на компоненте TcpClient.
Подскажите как сделать его более быстрым!

P.S. Использовал потоки(мб не правильно:))

Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Sockets, ComCtrls;

type
  TForm1 = class(TForm)
    TcpClient1: TTcpClient;
    host: TEdit;
    port2: TEdit;
    port1: TEdit;
    OpenPort: TMemo;
    Start: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    ProgressBar: TProgressBar;
    procedure StartClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TClThread = class(TThread)
    TcpClient1: TTcpClient;
    host:string;
    minPort,maxPort:string;
    procedure Execute; override;
    procedure LinesAdd;
  private
  public
  end;

var
  Form1: TForm1;
  skan:string;
  x,y:integer;
implementation

{$R *.dfm}

{ TClThread }

procedure TClThread.LinesAdd();  //добавляем порт в мемо
begin
   Form1.OpenPort.Lines.Add(IntToStr(x));
end;

procedure TClThread.Execute;
var
Client:TTcpClient;
begin
  inherited;
  Client:=TTcpClient.Create(nil);    //выделение памяти под переменную
 Client.RemoteHost:=host; //Установка адреса хоста

 x:=StrToInt(minPort);  //начальное и конечное значения портов
 y:=StrToInt(maxPort);
 //для красявости сделаем прогресбар
 Form1.ProgressBar.Min:=x;
 Form1.ProgressBar.Max:=y;

 while x<=y do                     //порбегаем по всем портам
 begin
 Client.RemotePort:=IntToStr(x);    //установка значения порта дла коннекта
 Client.Active:=true;

 if Client.Connect=true then     //если порт открыт то порт добавляется в мемо
 begin
 Synchronize ( LinesAdd );
 client.Disconnect;
 end
 else  client.Disconnect;

 Form1.ProgressBar.Position:=x;
 x:=x+1;

 end;
end;

procedure TForm1.StartClick(Sender: TObject);
var
trd:TClThread;
begin
if Start.Tag=0 then
begin
trd:=TClThread.Create(true);
start.Caption:='Stop';
host.Enabled:=false;
port1.Enabled:=false;
port2.Enabled:=false;

trd.host:=host.Text;
trd.minPort:=port1.Text;
trd.maxPort:=port2.Text;
start.Tag:=1;
trd.Resume;
end
else
 begin
 start.Caption:='Start';
host.Enabled:=true;
port1.Enabled:=true;
port2.Enabled:=true;
start.Tag:=0;
exit;
 end;

end;

end.
50K
25 апреля 2010 года
public_morozov
45 / / 06.01.2010
1. Все обращения к Form1 в Execute не thread-safe
2. Вы используете не потоки а поток! всего один, это равносильно его неиспользованию :) делите диапазон портов на несколько, например если он - 0 - 90, то делите на его на 3 потока по 30 портов каждому, и получите прирост скорости в 3 раза, либо вообще можете использовать по потоку на порт :)

Успехов!
2.2K
25 апреля 2010 года
S@tana
53 / / 15.10.2009
Цитата:
Вы используете не потоки а поток! всего один, это равносильно его неиспользованию делите диапазон портов на несколько, например если он - 0 - 90, то делите на его на 3 потока по 30 портов каждому, и получите прирост скорости в 3 раза, либо вообще можете использовать по потоку на порт


У меня вот вопрос возник. Как собственно разделить порты по потокам?
Пробовал сделать чтобы в Execute передавались параметры, но что то ничего не получается.
Примерчик бы очень помог. )

50K
25 апреля 2010 года
public_morozov
45 / / 06.01.2010
Передавайте не в Execute а в конструктор...

TForm1:
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, CheckThread, ComCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Edit1: TEdit;
    ProgressBar1: TProgressBar;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
    ProgressBar1.Max:=150;
    // From 1 to 50
    TCheckThread.Create(Edit1.Text,1,50,Memo1,ProgressBar1).Resume();
    // From 50 to 100
    TCheckThread.Create(Edit1.Text,50,100,Memo1,ProgressBar1).Resume();
    // From 100 to 150
    TCheckThread.Create(Edit1.Text,100,150,Memo1,ProgressBar1).Resume();
end;

end.


TCheckThread:
Код:
unit CheckThread;

interface

uses Classes, StdCtrls, SysUtils, Sockets, ComCtrls;

type TCheckThread = class(TThread)
    private
        FFromPort: integer;
        FToPort: integer;
        FOutput: TMemo;
        FHost: string;
        FTCP: TTcpClient;
        FProgress: TProgressBar;
    public
        procedure TryOutput();
        procedure FoundOutput();
        procedure Progress();
        procedure Execute(); override;
    published
        constructor Create(AHost: string; AFromPort, AToPort: integer; AOutput: TMemo; AProgress: TProgressBar); overload;
end;

implementation

{ TCheckThread }

constructor TCheckThread.Create(AHost: string; AFromPort, AToPort: integer; AOutput: TMemo; AProgress: TProgressBar);
begin
    inherited Create(true);
    Priority:=tpLowest;
    FFromPort:=AFromPort;
    FToPort:=AToPort;
    FOutput:=AOutput;
    FHost:=AHost;
    FProgress:=AProgress;
    FTCP:=TTcpClient.Create(nil);
end;

procedure TCheckThread.Execute;
begin
    while not Terminated do begin
        // You may to handle termination by OnTeminate Event
        if FFromPort = FToPort then Terminate;
        //Synchronize(TryOutput);
        Synchronize(Progress);
        FTCP.RemoteHost:=FHost;
        FTCP.RemotePort:=IntToStr(FFromPort);
        try
            FTCP.Connect();
            if FTCP.Connected then begin
                Synchronize(FoundOutput);
                FTCP.Disconnect();
            end;
        except
        end;
        // Next port
        Inc(FFromPort);
        Sleep(10);
    end;
end;

procedure TCheckThread.FoundOutput;
begin
    FOutput.Lines.Add('Found port: '+IntToStr(FFromPort));
end;

procedure TCheckThread.Progress;
begin
    FProgress.Position:=FProgress.Position+1;
end;

procedure TCheckThread.TryOutput;
begin
    FOutput.Lines.Add('Check port: '+IntToStr(FFromPort));
end;

end.


Здесь диапазон сканирования делится на 3 части (это я думаю Вы сможете реализовать) и каждая часть скармливается отдельному потоку. Так же в конструктор потока передается ссылка на объект вывода (Memo) и объект прогресса (ProgressBar). Надеюсь все будет понятно.

Успехов!
253
26 апреля 2010 года
Proger_XP
1.5K / / 07.08.2004
А почему никто не разрушает создаваемый TTcpClient? Что в первом коде, что во втором - конструктор перегружен, а деструктор - нет.
50K
26 апреля 2010 года
public_morozov
45 / / 06.01.2010
Цитата: Proger_XP
А почему никто не разрушает создаваемый TTcpClient? Что в первом коде, что во втором - конструктор перегружен, а деструктор - нет.



А это домашнее задание :)

Хотя я думаю, что достаточно будет в конструкторе добавить FreeOnTerminate:=true;

9.9K
26 апреля 2010 года
De_Montale
80 / / 23.08.2007
Хоть многие и чмырят Фленова Мишу, но в его книжке Delphi глазами хакера был тщательно разобран пример сканера портов в асинхронном режиме. Я проверял - работал оооочень даже шустро..правда некоторые места пришлось писать самому и на свой лад. Посмотри если интересно.
303
26 апреля 2010 года
makbeth
1.0K / / 25.11.2004
Зачем в этой задаче использовать TCPClient??? Можно просто обойтись стандартным WinSock API, вызывая его в синхронном режиме внутри потока. Тут с TCP клиентом проблема в том, что он сам по себе работает в асинхронном режиме, причем реализует событийный асинхронный режим (с использованием сообщений Windows). Из-за этого при использовании этого компонента в потоке могут возникнуть определенные проблемы.
public_morozov, зачем столько вызовов Synchronize в коде? Я уже где-то писал, что частое использование данного метода сводит на нет само понятие паралельного выполнения. Если уж хочется отобразить информацию о ходе выполнения потока, то нужно это сделать максимум одним вызовом Synchronize. Кроме того, не совсем ясно предназначение Sleep в конце цикла...
50K
26 апреля 2010 года
public_morozov
45 / / 06.01.2010
Цитата: makbeth
public_morozov, зачем столько вызовов Synchronize в коде? Я уже где-то писал, что частое использование данного метода сводит на нет само понятие паралельного выполнения. Если уж хочется отобразить информацию о ходе выполнения потока, то нужно это сделать максимум одним вызовом Synchronize. Кроме того, не совсем ясно предназначение Sleep в конце цикла...



Столько? их всего лишь 2, и все они обращаются к разным контролам и при разных условиях, и в вызываемых процедурах нет каких-либо вычислений чтобы они вдруг свели на нет параллельное выполнение. А Sleep в конце я считаю хорошей привычкой при использовании `бесконечных` циклов в потоках чтобы не загружать на 100% процессор при отсутствии из них выхода.

А TCPClient и правда из пушки по воробьям, но на данном этапе (создание представления о решении/работе) вполне нормальное явление

303
27 апреля 2010 года
makbeth
1.0K / / 25.11.2004
Цитата: public_morozov
Столько? их всего лишь 2, и все они обращаются к разным контролам и при разных условиях, и в вызываемых процедурах нет каких-либо вычислений чтобы они вдруг свели на нет параллельное выполнение.


Правда? А что по твоему происходит, скажем, вот здесь:

 
Код:
FProgress.Position:=FProgress.Position+1;
;)
...и до того как мы сюда попадем.
Цитата:
А Sleep в конце я считаю хорошей привычкой при использовании `бесконечных` циклов в потоках чтобы не загружать на 100% процессор при отсутствии из них выхода.

Здесь он не к чему. А если поток простаивает, то не слипами надо его разгружать, а функциями ожидания.

Цитата:
А TCPClient и правда из пушки по воробьям, но на данном этапе (создание представления о решении/работе) вполне нормальное явление

Я уже выше писал, почему он здесь не желателен.

1
27 апреля 2010 года
kot_
7.3K / / 20.01.2000
[COLOR="Red"]Если ты еще раз его напишешь - отправишься в бан за злостное нарушение правил топика.[/COLOR]
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог