Autor Beitrag
Highspeeder
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 34

Win 7
Delphi 7 Profesional,Visual Basic
BeitragVerfasst: Mi 05.07.06 01:58 
Hallo, ich will einen IP-Scanner programmieren und aus Geschwindigkeitsgründen mit mehreren Threads arbeiten.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
unit Unit1;

interface




uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  Sockets, StdCtrls,Strutils, jpeg, ExtCtrls;

type
  TForm1 = class(TForm)
    TcpClient1: TTcpClient;
    Starthost: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Port: TEdit;
    Button1: TButton;
    Memo1: TMemo;
    Endhost: TEdit;
    Label3: TLabel;
    Button2: TButton;
    Image1: TImage;



    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure weiter;
    procedure Ipget(Var Hostarray:Array of Integer;Str:String);
    procedure Ready;
    procedure ReadyCheck;

  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  Stop: Boolean ;
  Host1:Array [1..4of Integer;
  Host2: Array [1..4of Integer;

  PortAktuell:String;
  ThreadAnzahl:Integer;
  IPCounter: Array [1..100of String;
  Resultat: Array [1..100of String;
type
  TMyOwnThread = class(TThread)
  private
  CS:TTcpClient;
  public
  fertig:Boolean;
  Nummer:Integer;
  constructor Create(IPAddr,Port : string);
  destructor Destroy; override;
  protected
    procedure Execute; override;
  end;

var
  Thread: array [1..100of TMyOwnThread;

implementation

{$R *.dfm}

constructor TMyOwnThread.Create(IPAddr,Port : string);
begin
inherited Create(true);
// Der Parameter heißt CreateSuspended.
// Er hat zur Folge wenn wir ein false übergeben,
// dass der Thread sofort anfängt mit arbeiten.
// meist haben wir ihm dann aber noch gar keine Daten übergeben.
// also rufen wir ihm Suspended auf
CS := TTcpClient.Create(nil);
CS.RemoteHost:=IPAddr;
CS.RemotePort:=Port;
end;

destructor TMyOwnThread.Destroy;
begin
CS.Destroy;
inherited Destroy;
end;

procedure TMyOwnThread.Execute;
begin
  // Führe hier irgendwelche Berechnungen aus.
  fertig:=false;
  CS.Active := true;

  if CS.Connected = true then
  begin
  Resultat[Nummer]:=(CS.RemoteHost+'  '+'Port: '+CS.RemotePort+'  '+'open');
  end
  else
  begin
  Resultat[Nummer]:=(CS.RemoteHost+'  '+'Port: '+CS.RemotePort+'  '+'closed');
  end;

  CS.Active := false;
  fertig:=true;
  Form1.ReadyCheck;
end;





procedure TForm1.Button1Click(Sender: TObject);

Var I:Integer;

begin
IpGet(Host1,StartHost.Text);      //Start-IP-Adresse in 4 Zahlen auflösen
IpGet(Host2,Endhost.Text);        //End-IP-Adresse in 4 Zahlen auflösen
Stop:=false;
Memo1.Lines.Clear;
PortAktuell:=Port.Text;
ThreadAnzahl:=0;

While not Stop and (ThreadAnzahl<100do    //maximal 100 Threads
begin
Inc(ThreadAnzahl);
//Pro Thread je eine IP-Adresse erzeugen
IPCounter[ThreadAnzahl]:=IntToStr(Host1[1])+'.'+IntToStr(Host1[2])+'.'+IntToStr(Host1[3])+'.'+IntToStr(Host1[4]);

If (Host1[1]=Host2[1]) and (Host1[2]=Host2[2]) and (Host1[3]=Host2[3]) and
(Host1[4]=Host2[4]) then
begin
stop :=true;
end

else
begin
weiter;  //IP-Adresse um 1 erhöhen
end;
end;

For I:=1 to ThreadAnzahl do   //maximal 100 Threads erzeugen
begin
Thread[I] := TMyOwnThread.Create(IPCounter[I],PortAktuell);
Thread[I].Nummer:=I;
//Thread[I].FreeOnTerminate := True;
// FreeOnTerminate bedeutet sobald der Thread die Procedure Execute
// verlassen hat wird sein Speicher wieder von alleine Frei gegeben.
// andernfalls müsste später im Programm Thread.Free aufgerufen werden.
Thread[I].Execute;
// Falls der Thread suspended gestartet wurde sorgt dies dafür,
// dass er anfängt mit arbeiten.
end;
end;

procedure TForm1.weiter;

begin

inc(Host1[4]);
if Host1[4]>255 then
begin
Host1[4]:=0;
Inc(Host1[3]);
end;

if Host1[3]>255 then
begin
Host1[3]:=0;
Inc(Host1[2]);
end;

if Host1[2]>255 then
begin
Host1[2]:=0;
Inc(Host1[1]);
end;

if Host1[1]>255 then
begin
Dec(Host1[1]);
Stop:=true;
end;
end;

Procedure TForm1.ReadyCheck;
Var I:Integer;
    Go:Boolean;

begin
Go:=true;
//For I:=1 to ThreadAnzahl do
//begin
//If Thread[I].fertig = false then Go:=false;
//end;
If Go then Ready //alle Threads beendet----Ergebnisse in Memo1 ausgeben
end;

//Resultate in Memo1 ausgeben
procedure TForm1.Ready;
Var I:Integer;

begin
For I:=1 to ThreadAnzahl do
begin
//Thread[I].destroy;
//Thread[I].free;
Memo1.Lines.Add(Resultat[I]);
end;
end;

procedure Tform1.Ipget(Var Hostarray:Array of Integer;Str:String);

Var Punkt : Integer;

begin
Punkt:=Pos('.',Str);
Hostarray[0]:=StrToInt(Copy(Str,1,Punkt-1));
Str:=Copy(Str,Punkt+1,Length(Str));
Punkt:=Pos('.',Str);
Hostarray[1]:=StrToInt(Copy(Str,1,Punkt-1));
Str:=Copy(Str,Punkt+1,Length(Str));
Punkt:=Pos('.',Str);
Hostarray[2]:=StrToInt(Copy(Str,1,Punkt-1));
Str:=Copy(Str,Punkt+1,Length(Str));
Punkt:=Pos('.',Str);
if Punkt=0 then Hostarray[3]:=StrToInt(Str) else Hostarray[3]:=StrToInt(Copy(Str,1,Punkt-1));
end;


Meine Fragen :
Das sind maximal 100 Threads

1. Wie merke ich, wenn alle Threads fertig sind ?
2. Die Routine müßte dann mehrmals durchlaufen werden, also wenn ich 1000 IP-Adressen scannen will müßte das 10x passieren.
3. Warum bekomme ich eine Fehlermeldung,wenn ich If Thread[I].fertig = false then Go:=false; aufrufe ?
4. Ebenfalls Fehlermeldung bei Methoden Free und Destroy
5. Warum reagiert meine Anwendung bei der Ausführung der Threads nicht mehr ?
muß ich irgendwo synchronise verwenden ?

Vielen Dank schon mal im vorraus
crowley
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 406

Win XP, Win Vista, Mandriva, Ubuntu
Delphi 4-8, Delphi 2006, Delphi 2007
BeitragVerfasst: Mi 05.07.06 08:03 
kann nicht sofort zu allen deinen fragen eine antwort geben, aber so dreidinge sind mir abgesehen von der unleserlichen formatierung aufgefallen:

ich würde

ausblenden Delphi-Quelltext
1:
for i := 0 to ThreadAnzahl - 1 do					


verwenden.

Und ganz wichtiger Hinweis: NIEMALS bei einem Objekt Destroy direkt aufrufen. Free reicht... noch besser ist FreeAndNil.

Public Variablen in Objekten zu verwenden ist gaaaar nicht gut... kapsele das besser in einer Property...
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 05.07.06 08:39 
Moin!

Guckst du, threadbasierter Ping ist da schon eingebaut, mit Callback. ;)

cu
Narses

//EDIT: Ah, wer lesen kann, ist klar im Vorteil... :lol: ist ja gar kein Ping... ;) Sorry.

_________________
There are 10 types of people - those who understand binary and those who don´t.
Highspeeder Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 34

Win 7
Delphi 7 Profesional,Visual Basic
BeitragVerfasst: Mi 05.07.06 13:09 
@Crowley: Danke für den Beitrag.


Bei Threads gibt es folgende Möglichkeit :

Thread.FreeOnTerminate := True;
// FreeOnTerminate bedeutet sobald der Thread die Procedure Execute
// verlassen hat wird sein Speicher wieder von alleine Frei gegeben.
// andernfalls müsste später im Programm Thread.Free aufgerufen werden.

Dadurch wird automatisch auch destroy ausgeführt.

Thread.FreeandNil gibt es nicht.

Na ja..ob ich nun bei 1 oder 0 anfange zu zählen ist eigentlich egal.




@Narses: ein Musterbeispiel für Multithreading.
Durch die Methode synchronize friert meine Anwendung nicht mehr ein.
Allerdings habe ich nun ein neues Problem :
Wenn ich mit 100 Threads arbeite dann kommen unterschiedliche Ergebnisse raus.
TTcpClient meint mal Port 21 ist geschlossen, dann beim nächsten mal Port 21 ist offen.
Mit deiner Ping-Funktion kommt übrigens dann immer ein Timeout.
Kann das sein ? Port 21 offen und keine Pingantwort ?
Funktioniert denn das überhaupt noch richtig ?
Ich meine, wenn ich 100 Hosts anspreche, dann weiß ich ja nie ob der entsprechende Thread gerade bereit ist, um eine Antwort aufzunehmen.
Wenn ich nur 20 Threads nehme dann geht das so einigermaßen.

Vielleicht muß man auch mit TCriticalSection arbeiten...keine Ahnung
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 05.07.06 13:24 
Moin!

Es gibt eine Grenze für gleichzeitige TCP-Verbindungen. Deshalb kommt es vermutlich zu dem merkwürdigen Verhalten.

Nebenbei: ich halte es sowieso für fragwürdig, einen Port-Scanner in der von dir eingeschlagenen Weise (und dann noch mit so vielen Threads) zu realisieren.

Schau dir mal Suche bei Google NMAP an. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
crowley
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 406

Win XP, Win Vista, Mandriva, Ubuntu
Delphi 4-8, Delphi 2006, Delphi 2007
BeitragVerfasst: Mi 05.07.06 13:26 
schau mal in der Hilfe nach FreeAndNil -> das ist eine Funktion aus SysUtils.pas...

Schlussendlich macht FreeAndNil(MyThread) folgendes:
1.) MyThread.Free;
2.) MyThread := nil;

desweiteren hast du FreeOnTerminate auskommentiert
Highspeeder Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 34

Win 7
Delphi 7 Profesional,Visual Basic
BeitragVerfasst: Mi 05.07.06 13:53 
assarbad.net -> fastscan

der arbeitet sogar mit 256 Threads
alias5000
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2145

WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
BeitragVerfasst: Mi 05.07.06 14:08 
Aber eigentlich bringen so viele doch nix! So viele Prozessorkerne, wie man hat, so viele macht es ungefähr auch Sinn. Dass man das nicht im MainThread ablaufen lässt ist ja klar, warum. Aber je mehr Threads man hat, desto höher ist doch der Verwaltungsaufwand für Windows, desto mehr Zeit geht durch diese Organisation des Multitasking drauf und desto weniger bringen zusätzliche Threads, weils ja nicht wirklich gleichzeitig abläuft. Nur wenn man mehrere Kerne hat, dann läufts gleichzeitig ab und dann machen ein paar mehr Threads schon etwas mehr Sinn

Gruß alias5000

_________________
Programmers never die, they just GOSUB without RETURN
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 05.07.06 14:22 
Moin!

user profile iconalias5000 hat folgendes geschrieben:
Aber eigentlich bringen so viele doch nix! So viele Prozessorkerne, wie man hat, so viele macht es ungefähr auch Sinn.

Naja, grundsätzlich magst du Recht haben. Allerdings bringen hier mehrere Threads schon was, denn damit kannst du die Wartezeiten parallelisieren. ;)

@user profile iconHighspeeder: Wenn Assarbad mit so vielen Threads arbeitet, wird er schon wissen, welche Umgebung und Systemkonfiguration dafür nötig ist.
Ich meinte aber eher den Ansatz mit den TCP-Connects auf Basis der Indy-TCP-Kompo. Einen entsprechenden Scanner macht man besser mit RawSockets und dazugehörigem Hintergrundwissen über die Internetprotokollfamilie -> deshalb der nmap-Hinweis. ;)

[philosophie]Ich weiß nicht, warum Portscanner so einen unglaublichen Reiz ausüben, muss so ein "verboten-Flair" haben, in Richtung hacken, dabei kommt man sich dann vermutlich cool vor. :roll: "Echte Hacker" würden wahrscheinliche lieber eine funktionierende Lösung nehmen, als sich mit sowas aufzuhalten, deshalb frage ich mich immer wieder, warum man sich ausgerechnet daran "üben" muss, statt eine sinnvolle Netzwerkapplikation zu programmieren - damit kann man genausoviel lernen, aber nervt andere weniger.[/philosophie]

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
alias5000
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2145

WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
BeitragVerfasst: Mi 05.07.06 14:29 
user profile iconNarses hat folgendes geschrieben:
user profile iconalias5000 hat folgendes geschrieben:
Aber eigentlich bringen so viele doch nix! So viele Prozessorkerne, wie man hat, so viele macht es ungefähr auch Sinn.

Naja, grundsätzlich magst du Recht haben. Allerdings bringen hier mehrere Threads schon was, denn damit kannst du die Wartezeiten parallelisieren. ;)


Stimmt, das hab ich übersehen :roll: :wink:

_________________
Programmers never die, they just GOSUB without RETURN
Highspeeder Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 34

Win 7
Delphi 7 Profesional,Visual Basic
BeitragVerfasst: Mi 05.07.06 14:45 
Ja die Threads sollen die Geschwindigkeit erhöhen.
Immerhin kann es sein das man mal eine oder 2 Sekunden warten muß, bis eine Antwort vom Host kommt.
Und wenn ich alle Ports nachguggen will, dann sind das immerhin 65000 Stück oder so.
Ja..mit nem Scanner kann man anonyme Mailserver oder Proxys suchen..nur mal zum Beispiel (oder Trojaner).
Dann könnte man die Ergebnisse in einer Datenbank speichern.

Ich persönlich finde Nmap halt ätzend, weil das auf Kommandozeilenebene läuft.
Da geht gar nix mit automatisieren.
Mußt die Kommandos im Kopf haben und ellenlange Befehle eintippen.

Im übrigen will ich nicht nerven sondern was eigenes programmieren.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 05.07.06 15:11 
Moin!

user profile iconHighspeeder hat folgendes geschrieben:
Im übrigen will ich nicht nerven sondern was eigenes programmieren.

Schon klar, du willst einen Portscanner zu rein "theoretischen Zwecken" schreiben... :roll: :lol:

Fühl dich nicht angegriffen, es war nicht persönlich gemeint. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Highspeeder Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 34

Win 7
Delphi 7 Profesional,Visual Basic
BeitragVerfasst: Mi 05.07.06 15:15 
nett lachen..aber ich hab vorher noch nie nen Thread programmiert.
alias5000
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2145

WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
BeitragVerfasst: Mi 05.07.06 16:26 
Ist dir klar, was ein Thread macht, weißt du, wie das Multitasking in Windows 95 aufwärts funktioniert, welche Probleme dabei drohen?
Ich hab mir das ganze mal theoretisch angeeignet und bin heilfroh drum, weil man sonst nicht weiß, was wirklich passiert. gDeswegen kann man Threads schlecht mit Try&error erlernen (finde ich).

Jetzt brauchste nur noch ne Quelle, hm...
Ich glaube zwar nicht, dass du hier ein ausführliches Tut findest, aber such mal in der EE, DP, Swissdelphicenter, dsdt.info und schließlich google. Hilft das nix und keiner bringt hier noch was, kann ich auf den Weg zur Bibliothek verweisen, dort findest du sicher ein Buch, das ausführlich in die Materie einführt (das war mein Weg)

Gruß alias5000

_________________
Programmers never die, they just GOSUB without RETURN