Hi Leute
Für einen LAN-Messenger suche ich nach einer Möglichkeit um zuverlässig und relativ schnell mittels
TCP Protokoll einen Server auf einem bestimmten Port zu finden. Ich habe schon ca. 2 Tage rumprobiert und bin einfach nicht auf eine vernünftige Lösung gekommen, deshalb seid ihr meine letzte Hoffnung!
Also... ich will alle IPs von 192.168.1.1 bis 192.168.1.255 auf dem Port 6000 ab scannen ob da meine Software (also der Messenger läuft). Ich habe es bisher mit mehreren Threads (TThread) versucht, zuerst mit 255 Threads die GLEICHZEITIG verbunden haben, dies schlug fehl. Dann alle 255 Threads mit Suspended = True erstellt und dann nacheinander gestartet... dies funktionierte ebenfalls nicht.
Nun hab ich es so gemacht, dass ich zuerst eine Art Jobliste erstelle mit allen IPs drin.
Dann noch eine Art Threadliste (keine TThreadList!) welche am Anfang 5 Threads zugewiesen bekommt, welche dann überwacht werden und sobald einer beendet ist, ein neuer Thread erstellt wird mit dem nächsten "Job" (
IP). So das immer genau 5 Threads arbeiten
Naja... dies will jedoch auch weder zuverlässig noch genügend schnell arbeiten
Genauer gesagt arbeitet er so für ca. 10 Threads korrekt, bleibt dann aber etwa 20 Sekunden hängen bevor er weiterarbeitet, das Problem ist gelöst wenn ich ein Sleep mit 1 Sekunden reinsetze. Aber es sollte doch schneller gehen oder?
Ich habe das Gefühl dass mir die TIdThreads dazwischenfunken
Ich muss noch anmerken, dass ich zum 1. Mal mit Threads arbeite, habe da noch keine Erfahrungen.
Hier noch bisschen Code damit ihr euch auch mehr darunter vorstellen könnt als bei meiner Erklärung
Hier sind mal die Klassendefinitionen:
TSearchThread = Der "Chef"-Thread, er wird vom Hauptprogramm instanziert und steuert den ganzen Ablauf.
TWorkers = Die Liste der laufenden Threads
TWorker = Der "Arbeiter"-Thread, der Thread der den eigentlichen Verbindungsversuch ausführt. Er enthält den IdTCPClient und sollte dann eigentlich auch zurückliefern ob die Verbindung erfolgreich war oder nicht. Hatte ich bei meinem 1. Anlauf noch drin, später wieder rausgenommen weils vorerst unwichtig war. (Habt ihr da auch eine Idee wie ich das am besten realisieren könnte?)
TJobList = Die oben erwähnte Jobliste. Sie wird mit den IPs von 192.168.1.1 bis 192.168.1.255 aufgefüllt welche dann einzeln abgearbeitet werden.
Delphi-Quellcode:
TWorker =
class(TThread)
private
client: TIdTCPClient;
protected
procedure Execute;
override;
public
IP:
string;
Connected: boolean;
Running: boolean;
end;
TWorkers =
class(TObject)
private
protected
public
Threads:
Array of TWorker;
end;
TJobList =
class(TStringList)
private
protected
public
function GetNextJob:
String;
end;
TSearchThread =
class(TThread)
private
NewItem:
string;
JobList: TJobList;
Workers: TWorkers;
protected
procedure Execute;
override;
procedure AddTreeItem;
procedure RunCheck(
Index: integer);
public
IP:
string;
Connected: boolean;
end;
Und noch die einzelnen Prozeduren:
Delphi-Quellcode:
procedure TSearchThread.Execute;
var
i: Integer;
begin
JobList := TJobList.Create;
Workers := TWorkers.Create;
for i := 0
to 255
do
begin
JobList.Add('
192.168.1.'+IntToStr(i));
end;
for i := 0
to 5
do
begin
SetLength(Workers.Threads, Length(Workers.Threads)+1);
Workers.Threads[i] := TWorker.Create(true);
Workers.Threads[i].IP := JobList.GetNextJob;
Workers.Threads[i].Resume;
end;
while JobList.Count > 0
do
begin
for i := 0
to Length(Workers.Threads)-1
do
begin
if not Workers.Threads[i].Running
then
begin
NewItem := '
Thread '+IntToStr(i)+'
wurde beendet';
Synchronize(AddTreeItem);
Workers.Threads[i] := TWorker.Create(true);
Workers.Threads[i].IP := JobList.GetNextJob;
Workers.Threads[i].Resume;
end;
Sleep(500);
end;
end;
end;
procedure TSearchThread.AddTreeItem;
begin
frmMain.treeContacts.Items.AddChild(
nil, NewItem);
end;
procedure TWorker.Execute;
begin
Running := true;
client := TIdTCPClient.Create;
client.Port := 60000;
client.ConnectTimeout := 500;
client.Host :=
IP;
try
client.Connect;
except
end;
if client.Connected
then
begin
Connected := true;
end
else
begin
Connected := false;
end;
client.Free;
Running := false;
end;
function TJobList.GetNextJob:
string;
begin
Result := self.Get(0);
self.Delete(0);
end;
Ich hoffe ihr Profis *gg* könnt etwas damit anfangen und mir helfen... Wär echt toll
Danke im voraus!
Cu
Schönen Abend noch
Kill0r