-
набросал минимальный примерчик, для пояснения сути вопроса
Вот кусок примерный кода для пояснения вопроса:
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, TrayIcon, Menus, ZAbstractConnection, ZConnection, StdCtrls,
Buttons, ExtCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient, IdTelnet, DB, ZAbstractRODataset, ZAbstractDataset, ZDataset, DateUtils;
type
TMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
procedure TimerTimer(Sender: TObject);
private
IPList: TStringList;
ThreadArray: array of TThread;
PredScanTime: TDateTime;
public
end;
TTelnetThread = class(TThread)
private
IdTelnet: TIdTelnet;
PortNo: Integer;
IP: String;
LastPortText: String;
procedure ParsePortText;
procedure DataAvailable(Sender: TIdTelnet; const Buffer: String);
protected
procedure Execute; override;
public
constructor Create(IP: String);
end;
var
MainForm: TMainForm;
implementation
procedure TMainForm.FormCreate(Sender: TObject);
var
i,j: Integer;
begin
IPList := TStringList.Create;
IPList.LoadFromFile(ExtractFileDir(Application.ExeName)+'\IP.txt');
PLList := TStringList.Create;
PredScanTime := Now;
SetLength(ThreadArray, IPList.Count);
end;
constructor TTelnetThread.Create(IP: String);
begin
inherited Create(True);
IP := IP;
LastPortText := '';
end;
procedure TTelnetThread.DataAvailable(Sender: TIdTelnet; const Buffer: String);
begin
LastPortText := LastPortText + Buffer;
end;
procedure TTelnetThread.ParsePortText;
begin
1) Парсим текст
2) Вставляем в базу
end;
procedure TMainForm.TimerTimer(Sender: TObject);
var
i: Integer;
begin
if DateTimeToUnix(Now) > DateTimeToUnix(PredScanTime) + 300 then begin
PredScanTime := Now;
for i := 0 to Length(ThreadArray) - 1 do begin
ThreadArray[i] := TTelnetThread.Create(IPList[i],PLList[i]);
ThreadArray[i].FreeOnTerminate := True;
ThreadArray[i].Priority := tpLower;
ThreadArray[i].Resume;
end;
end;
end;
procedure TTelnetThread.Execute;
var
i: Integer;
begin
try
IdTelnet := TIdTelnet.Create(nil);
IdTelnet.OnDataAvailable := DataAvailable;
IdTelnet.Host := IP;
IdTelnet.Connect(-1);
Sleep(2000);
IdTelnet.Write('admin'+#13#10);
Sleep(2000);
IdTelnet.Write('admin'+#13#10);
except
end;
try
for i := 1 to 64 do begin
LastPortText := '';
PortNo := i;
IdTelnet.Write('get port '+IntToStr(i)+' data'+#13#10);
sleep(1500);
Synchronize(ParsePortText);
end;
except
end;
IdTelnet.Free;
end;
end;
end.
Чем больше потоков, тем больше в БД пустых записей, до 30 потоков все 30X(64порта) =1960 записей на месте. Дальше чем больше потоков тем больше пустых в квадратичной прогрессии. В чем костыль?
-
> aka © (09.11.17 14:31)
а что отладчик говорит по поводу работы с IdTelnet?
-
В древнем Китае людям, глушащим исключения, отрубали голову. Очень мудро поступали.
-
> Игорь Шевченко © (10.11.17 12:01) [2]
)) Да я просто постирал, чтобы топик был меньше и читаймей
-
> Eraser © (10.11.17 00:35) [1] > > > > aka © (09.11.17 14:31) > > а что отладчик говорит по поводу работы с IdTelnet?
Переменная LastPortText (которую и должны парсить) пустая. Но до конца пока не разобрался все равно в чем причина.
Сделал сканирование в 3 очереди по 33,33,34 потока на 100 IP адресов. и все 64х100=6400 порта четко "ответили". Три дня идет сканирование каждые 30 мин и из 6400 * 48 *3 все ответило.
Но стоит сделать чуть больше 40 потоков за раз и начинаются "дырки"
-
> Игорь Шевченко © (10.11.17 12:01) [2]
Игорь, ну что вам тяжело было сразу подсказать в чем вся загвоздка?
вот на sql.ru сразу все объяснили))) :
а ничего, что Microsoft настоятельно рекомендует не использовать в программе потоков количеством более, чем число ядер процессоров в системе * 2? У тебя банально операционка не дает квантов времени на выполнение потокам
Прокомментируйте.
-
aka © (10.11.17 16:56) [5]
там дальше столько всего написали :)
-
Нужно будет попробовать после выходных IdTelnet.ThreadedEvent = true
-
> aka © (10.11.17 19:09) [7]
так он не синхронный по умолчанию что-ли? странно для индивых компонентов. конечно надо ставить, чтобы все было в отдельном потоке. желательно последовательно и синхронно. результат работы потока лучше всего получать через OnTerminate, которое выполняется в контексте основного потока, т.к. не нужно явно вызывать Synchronize.
-
> так он не синхронный по умолчанию что-ли?
Ну получается что DataAvailable в основном потоке procedure TTelnetThread.DataAvailable(Sender: TIdTelnet; const Buffer: String);
begin
LastPortText := LastPortText + Buffer;
end; А я думал "что все как положено"
-
property ThreadedEvent: Boolean;
ThreadedEvent is a Boolean property that indicates if data handling and protocol suboption negotiations are executed in the context of the TelnetThread or synchronized to the main VCL thread for the application. Data handling and protocol negotiations are performed using the OnDataAvailable and the OnTelnetCommand event handlers.
When ThreadedEvent contains True, event handlers notifications are executed in the context of the TelnetThread.
When ThreadedEvent contains False, event handler notifications are synchronized to the main VCL thread. Set ThreadedEvent to False when the event handlers are not thread-safe or require access to classes and routines available only in the main VCL thread.
The default value for ThreadedEvent is False.
-
> Eraser © (11.11.17 03:22) [10]
Нужно было это прочитать чуть раньше.
-
Удалено модератором
|