Einzelnen Beitrag anzeigen

Kill0r

Registriert seit: 5. Jun 2005
Ort: Zürich
50 Beiträge
 
Delphi 2010 Professional
 
#1

Server im LAN finden mittels IdTCPClient

  Alt 29. Mai 2007, 21:35
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
  Mit Zitat antworten Zitat