Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   indy Server und Client komponente (https://www.delphipraxis.net/166292-indy-server-und-client-komponente.html)

youuu 6. Feb 2012 19:05

indy Server und Client komponente
 
Hi,

ich benutze die Indy Komponente um von einem Client an den Server Daten zu senden.

von Client zum Server funktioniert alles wunderbar, aber vom Server zum Client gibt es immer einen Socket Error.
Kann es sein, das die IP des clients nicht korrekt ist, da dieser hinter einen Router steckt?

Wenn ja, wie kann man das Problem lösen?

Klaus01 6. Feb 2012 21:15

AW: indy Server und Client komponente
 
Guten Abend,

server (öffentliche IP-Adresse) ---- (öffentliche IP-Adresse)-Router-(private IP-Adresse)-Client

Wie versuchst Du denn vom Server den Client zu erreichen?

Wenn Client zum Server funktioniert, dann ist (TCP vorausgesetzt) eine Verbindung zustande gekommen.
Eine TCP Verbindung ist in der Regel nicht unidirektional. D.h. der Server kann über den gleichen Weg/die gleiche Verbindung etwas zum Client schicken.

Grüße
Klaus

mjustin 7. Feb 2012 10:05

AW: indy Server und Client komponente
 
Zitat:

Zitat von youuu (Beitrag 1149523)
aber vom Server zum Client gibt es immer einen Socket Error.

Welcher Socket Error ist es denn genau (es gibt viele)? Und wie sieht der Quelltext aus (von Server zu Client)?

youuu 8. Feb 2012 14:33

AW: indy Server und Client komponente
 
Entschuldigung, war leider etwas beschäftigt.

Fehler wenn ich vom Server zurück senden möchte ist "Connection Time out"


So sende ich dann zurück:

Delphi-Quellcode:

procedure TForm1.TCPServerExecute(AContext: TIdContext);
begin
  TCPClient.Host := AContext.Binding.PeerIP;
  TCPClient.Connect;
  if TCPClient.Connected then begin
    TCPClient.IOHandler.WriteLn('bla bla');
    TCPClient.Disconnect;
  end;
end;
Also sobald ich eine Nachricht vom Client erhalte, setze ich als Host seine Ip ein und möchte zurück senden.

mjustin 8. Feb 2012 15:21

AW: indy Server und Client komponente
 
Zitat:

Zitat von youuu (Beitrag 1149884)

Delphi-Quellcode:
procedure TForm1.TCPServerExecute(AContext: TIdContext);
begin
  TCPClient.Host := AContext.Binding.PeerIP;
  TCPClient.Connect;
  if TCPClient.Connected then begin
    TCPClient.IOHandler.WriteLn('bla bla');
    TCPClient.Disconnect;
  end;
end;
Also sobald ich eine Nachricht vom Client erhalte, setze ich als Host seine Ip ein und möchte zurück senden.

Ich nehme an, TCPClient ist die Indy Client-Komponente, die sich zuvor mit dem Server verbunden hat?

Die darf der Server darf nicht einfach "wiederverwenden". Eigentlich sollte man, um diesen Fehler auszuschliessen getrennte Projekte anlegen (eines für Clients, und eines für Server).

Der Server hat ja schon seit dem Verbindungsaufbau eine stehende Clientverbindung. Deren Socket (IOHandler) kann vom Server benutzt werden um Daten an den Client zu senden.

Nur muss der Server dazu auch die 'richtige' Connection finden, falls mehrere Clients mit dem Server verbunden sind.

Ich habe aber gerade keinen kompletten Beispielcode zur Hand, eigentlich müßte in den Indy Demos etwas sein...

Klaus01 8. Feb 2012 15:29

AW: indy Server und Client komponente
 
Hallo,

im Prinzip sollte es so gehen.

Delphi-Quellcode:
procedure TConfigService.onExecute(AContext: TIdContext);
  begin
    AContext.Connection.IOHandler.ReadBytes(key,16); // TCP server liest
    AContext.Connection.IOHandler.Write(buffer.Size); // TCP server schickt etwas zum client
    AContext.Connection.IOHandler.Write(buffer,buffer.size); // wie oben
  end;
Grüße
Klaus

mjustin 8. Feb 2012 15:46

AW: indy Server und Client komponente
 
Zitat:

Zitat von Klaus01 (Beitrag 1149905)
Delphi-Quellcode:
procedure TConfigService.onExecute(AContext: TIdContext);
  begin
    AContext.Connection.IOHandler.ReadBytes(key,16); // TCP server liest
    AContext.Connection.IOHandler.Write(buffer.Size); // TCP server schickt etwas zum client
    AContext.Connection.IOHandler.Write(buffer,buffer.size); // wie oben
  end;

Genau so ist es (wenn TConfigService ein TIdTCPServer ist) :)

Wichtiges Detail:

OnExecute wird vom TIdTCPServer in einer Schleife immer wiederholt (bis die Verbindung endet).

Man kann den Code noch etwas CPU freundlicher machen (Quelle). Wichtig sind die Kommentare, die ein anderes Vorgehen beschreiben als im Quelltext darüber.

youuu 8. Feb 2012 15:48

AW: indy Server und Client komponente
 
Danke, nun klappt alles :)

mjustin 8. Feb 2012 15:58

AW: indy Server und Client komponente
 
Hier die stromsparende Variante, nach http://stackoverflow.com/a/544473/80901 (unter Berücksichtigung der Anmerkungen von Remy Lebeau):

Delphi-Quellcode:
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext);
var
  RxBuf: TIdBytes;
begin
  RxBuf := nil;
  with AContext.Connection.IOHandler do
  begin
    if InputBufferIsEmpty then
    begin
      CheckForDataOnSource(10);
   
      if InputBufferIsEmpty then
      begin
        Exit;
      end;

      InputBuffer.ExtractToBytes(RxBuf);

      // process RxBuf as needed...

    end;
  end;
end;
p.s. in diesem Beispiel sendet der Client einen Request, der dann vom Server verarbeitet wird.

Es kann aber im OnExecute Handler als erstes eine Nachricht an den Client gesendet werden. Zum Beispiel, wenn der Server eine interne Queue von Daten hat, die er nach und nach an den Client senden soll.

In diesem Fall würde der OnExecute Handler anders aufgebaut:

* hole ein Element aus der Queue
* falls kein Element vorhanden war, Exit
* sonst: schreibe die Daten an den Client - AContext.Connection.IOHandler.WriteLn(Daten);
* fertig (es sei denn, eine "synchrone" Quittung des Clients wird benötigt, dann weiter mit CheckForDataOnSource(TimeOut);


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:17 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz