Einzelnen Beitrag anzeigen

armageddon7007

Registriert seit: 2. Okt 2003
2 Beiträge
 
#4

Re: IdTCPServer - String an ALLE Clients!

  Alt 2. Okt 2003, 12:56
Das ganze kann man schon machen und ist eigentlich auch nicht so schwierig.

Habe leider keinen Beispiel-Source, aber mit den Demos von Indy kann man sich das bauen.

Um erstmal alle verbundenen Clients zu ermitteln, gibt es eine einfache Methode, die ich immer benutze.

Zuerst muß man eine eigene Klasse definieren, die zumindest eine Variable vom Typen TIDPeerThread besitzt und ein TList-Object erstellen.
Diese Klasse (hier TClientClass) wird im OnConnect für jede eingehende Verbindung erstellt und der Data-Property von AThread übergeben und der Verweis auf AThread.Data zur Liste (hier fCLientList) hinzugefügt. Dann setzt man im erstellten Object noch die TIDPeerThread-Variable:

Delphi-Quellcode:
procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
  AThread.Data:= TClientClass.Create();
  fClientList.Add(AThread.Data);
  TClientList(AThread.Data).faThread:= AThread;
end;
Im OnDisconnect vom Server muß dann dieser Eintrag wieder gelöscht werden. Das vorher erstellte Object braucht man nicht freigeben, das mach AThread alleine, wenn Data<>nil ist. Will man trotzdem das erstellte Object selber freigeben, muß man danach auf jeden Fall Data auf nil setzen.

Delphi-Quellcode:
procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
begin
  fClientList.Delete(fClientList.IndexOf(AThread.Data));
end;
Will man nun allen Clients einen String senden, kann man das über das TList-Object machen:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
begin
  for i:=0 to fCLientList.Count-1 do begin
    if TClientClass(fClientList[i]).fAThread.Connection.Connected then begin
      TClientClass(fClientList[i]).fAThread.Connection.WriteLn('Hallo');
    end;
  end;
end;


Im Client sieht das dann schon ein bißchen anders aus, dort muß man einen Thread erstellen, der die ganze Zeit ein Read vom IDTCPCLient macht. Dazu sollte man den Wert von ReadTimeOut auf jeden Fall sehr niedrig setzen (z.B. 250ms).
Zudem braucht man eine Semaphore, mit der man absichert, dass der Thread nur dann ein Lesebefehl ausführt, während von anderen Programmteilen nichts gesendet oder gelesen wird.

Dann locked man die Semaphore wenn man selber etwas senden oder lesen möchte und in der Zeit wird der Thread nicht versuchen, etwas zu lesen, da dieser natürlich auch versucht die Semaphore zu bekommen, bevor dieser versucht etwas vom idTCPClient zu lesen.

Damit sollte das eigentlich klappen.

Hoffe du kannst damit was anfangen, ansonsten habe ich die tage bestimmt mal zeit ein kleines Demo zu schreiben.
  Mit Zitat antworten Zitat