Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Mit Server auf OnConnect reagieren wie? (https://www.delphipraxis.net/200684-mit-server-auf-onconnect-reagieren-wie.html)

holger_barntrup 15. Mai 2019 11:42

Mit Server auf OnConnect reagieren wie?
 
Hallo zusammen
Nach Ewigkeiten mal wieder ein Beitrag. ;)
Ich hatte mir mal ein ein Beispiel für einen Server heruntergeladen und etwas damit herumprobiert.
Was ich nicht hin bekomme ist bei einem Connect eines Clients dem zu antworten.

Hier mal der Code (Ist auch hier aus dem Forum):



Code:
unit UFrmServer;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, ExtCtrls, IdTcpServer, IdContext,
  IdBaseComponent, IdComponent, IdCustomTCPServer;

type
  TfrmServer = class(TForm)
    pnlConnection: TPanel;
    editPort: TEdit;
    pnlPort: TPanel;
    Panel1: TPanel;
    editIp: TEdit;
    btnStart: TButton;
    ListBox1: TListBox;
    procedure btnStartClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);

  private
    FServer: TIdTCPServer;
    { Private-Deklarationen }
  protected
    procedure OnExecuteEventHandler(AContext: TIdContext);

  public
    { Public-Deklarationen }
  end;

var
  frmServer: TfrmServer;

implementation

{$R *.dfm}

procedure TfrmServer.btnStartClick(Sender: TObject);
begin
  // Ein TCP-Server nimmt Anfragen einer bestimmten Adresse entgegen und
  // beantwortet diese entsprechend einem bestimmten Protokoll

  // Binden der IP Adresse
  self.FServer.Bindings.Items[0].IP := self.editIp.Text;
  // Binden des Ports
  self.FServer.Bindings.Items[0].Port := StrToInt(self.editPort.Text);

  // Die Adresse(n), auf denen der Server Anfragen entgegen nimmt setzen sich
  // aus einer IP und einem Port zusammen. Durch das Binden wurde nun eine
  // solche Adresse zugewiesen, kommen Anfragen, die an diese Adresse gerichtet
  // werden an, so wird der Server sie beantworten

  // Hier wird der Server aktiviert, er wartet nun aktiv auf Anfragen!
  self.FServer.Active := True;

  // Den Start samt Uhrzeit einfach in der Listbox anzeigen, damit man sieht
  // das der Server gestartet wurde (optional!)
  self.ListBox1.Items.Add(FormatDateTime('hh:mm:ss', now) + ' Server Started');
end;

procedure TfrmServer.FormCreate(Sender: TObject);
begin
  // Dynamisches Erzeugen eines Servers (das klappt auch mit der Turbo Delphi
  // Explorer Edition)
  self.FServer := TIdTCPServer.Create(self);
  // Zuweisen des OnExecute Events
  // Dieses wird benötigt, wenn der Server aktiviert wird
  // Es wird endlos immer wieder ausgeführt (darin besteht die gesamte Arbeit
  // des Servers)
  self.FServer.OnExecute := self.OnExecuteEventHandler;
  // Hinzufügen einer neuen Bindung (siehe btnStartClick)
  self.FServer.Bindings.Add;
end;


procedure TfrmServer.OnExecuteEventHandler(AContext: TIdContext);
begin

  // Hier findet die eigentliche Arbeit des Servers statt. In einem neben-
  // läufigen Prozess wird diese Prozedur immer wieder aufgerufen

  // Einfache Idee hier, es wird eine Zeile eingelesen und (mit Uhrzeit in die
  // Listbox geschrieben
  // Das eigentliche Lesen der Zeile geschieht dabei durch
  // AContext.Connection.IoHandler.Readln

  // AContext ist das Argument dieser Methode, der Context, in dem die
  // Methode aufgerufen wurde
  // Die Eigenschaft Connection gibt einem die etablierte Verbindung zurück
  // IoHandler enthält den "Handler" für Input/Output-Ereignisse. Dieser bietet
  // die Methode Readln an. Diese blockiert, bis Daten ankommen, liest hier die
  // Daten als String aus, bis ein Zeilenende auftritt und gibt liefert diesen
  // String
  // Werden keine Daten empfangen, blockiert die Methode (wartet bis etwas
  // ankommt)
  self.ListBox1.Items.Add(FormatDateTime('hh:mm:ss', now) + ' Received Data: ' +
                          AContext.Connection.IOHandler.ReadLn);





  // Wurde ein String empfangen, kann es noch interessant sein, von wem dieser
  // String kam. Im Kontext dieser Verbindung findet sich in der Eigenschaft
  // Binding die angesprochene Adresse des Servers (hier wird nur eine gebunden,
  // aber es sind mehrere möglich) und die Adresse des Anfragestellers
  // PeerIp und PeerPort (Anfragesteller) werden mit in die Listbox übernommen
  self.ListBox1.Items.Add(FormatDateTime('hh:mm:ss', now) +
                          Format('Received from: %s:%d',
                                 [AContext.Binding.PeerIP,
                                  AContext.Binding.PeerPort]));

   if AContext.Connection.IOHandler.ReadLn = 'OFF' then AContext.Connection.IOHandler.WriteLn( 'OFF wurde erfolgreich uebermittelt'+#10+#13);


end;

end.

mjustin 15. Mai 2019 12:28

AW: Mit Server auf OnConnect reagieren wie?
 
Sendet der Client nach dem Aufbau der Verbindung einen definierte Nachricht (wie z.B. "HELLO" oder "LOGIN")?

Oder macht der Client nur die Verbindung auf und der Server soll dann etwas an diese Verbindung senden?


p.s. im Beispielcode wird aus dem Server-Thread auf ein VCL Element (Listbox1) zugegriffen, das ist nicht threadsafe.

holger_barntrup 15. Mai 2019 12:41

AW: Mit Server auf OnConnect reagieren wie?
 
Zitat:

Zitat von mjustin (Beitrag 1432286)

Oder macht der Client nur die Verbindung auf und der Server soll dann etwas an diese Verbindung senden?

Genau so, sobald die Verbindung besteht soll der Server eine Kennung (ASCII) senden.

holger_barntrup 15. Mai 2019 12:42

AW: Mit Server auf OnConnect reagieren wie?
 
Zitat:

Zitat von mjustin (Beitrag 1432286)

p.s. im Beispielcode wird aus dem Server-Thread auf ein VCL Element (Listbox1) zugegriffen, das ist nicht threadsafe.

Das ist auch nur für das Beispiel so. Was meinst du genau mit threadsafe?

holger_barntrup 16. Mai 2019 07:17

AW: Mit Server auf OnConnect reagieren wie?
 
Das muss doch irgendwie möglich sein bei dynamisch erzeugtem Server auf das OnConnect Ereignis zu reagieren. :roll:

Schokohase 16. Mai 2019 08:05

AW: Mit Server auf OnConnect reagieren wie?
 
Zitat:

Zitat von holger_barntrup (Beitrag 1432313)
Das muss doch irgendwie möglich sein bei dynamisch erzeugtem Server auf das OnConnect Ereignis zu reagieren. :roll:

Natürlich, sobald du dem OnConnect-Event einen passenden Event-Handler zuweist, wird das auch passieren.

mjustin 16. Mai 2019 14:31

AW: Mit Server auf OnConnect reagieren wie?
 
Beispielcode (mit Konsolenausgabe anstatt Listbox).

Hinweise:
  • das Erzeugen eines neuen Bindings ist nicht notwendig, standardmäßig wird beim Starten eines Indy TCP Servers bereits ein Binding erzeugt, mit IP 0.0.0.0. Im Code wird dann nur noch der Port gesetzt (über die DefaultPort-Property)
  • als Port verwendet das Beispiel den Telnet-Port, daher kann man mit 'telnet localhost' auf der Kommandozeile die Verbindung testen
  • der Server meldet sich nach dem Verbindungsaufbau mit der Ausgabe 'Welcome to Indy TCP Server example' und trennt nach einer Sekunde die Verbindung wieder

Delphi-Quellcode:
unit Unit1;

interface

uses
  IdTCPServer, IdContext,
  Classes, SysUtils, Forms, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FServer: TIdTCPServer;

    procedure Log(const Msg: string);

    procedure OnConnect(AContext: TIdContext);
    procedure OnExecute(AContext: TIdContext);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
  FServer.Active := True;

  Log('Server is listening');
  Log('Bindings[0].IP=' + FServer.Bindings[0].IP);
  Log('Bindings[0].Port=' + IntToStr(FServer.Bindings[0].Port));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FServer := TIdTCPServer.Create(Self);

  FServer.OnExecute := OnExecute;
  FServer.OnConnect := OnConnect;

  FServer.DefaultPort := 23; // Telnet Port
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FServer.Active := False;
end;

procedure TForm1.Log(const Msg: string);
begin
  WriteLn(Msg); // Ausgabe setzt Linken als "Konsolenanwendung" voraus
end;

procedure TForm1.OnConnect(AContext: TIdContext);
begin
  Log('CONNECT');
  Log(AContext.Binding.PeerIP);

  AContext.Connection.IOHandler.WriteLn('Welcome to Indy TCP Server example');

  Log('Welcome message sent');
end;

procedure TForm1.OnExecute(AContext: TIdContext);
begin
  Sleep(1000);

  AContext.Connection.IOHandler.WriteLn('Bye');

  AContext.Connection.Disconnect;
end;

end.

holger_barntrup 17. Mai 2019 05:50

AW: Mit Server auf OnConnect reagieren wie?
 
Hallo Michael
Vielen Dank für dein Beispiel. Ich glaub das bringt mich schon mal ein wenig weiter. :idea:

Das hier verstehe ich nur gar nicht:
Delphi-Quellcode:
  WriteLn(Msg); // Ausgabe setzt Linken als "Konsolenanwendung" voraus

Wie linkt man als "Konsolenanwendung" :?:

holger_barntrup 17. Mai 2019 10:38

AW: Mit Server auf OnConnect reagieren wie?
 
Zitat:

Zitat von holger_barntrup (Beitrag 1432378)
Wie linkt man als "Konsolenanwendung" :?:

Selber herausgefunden.

Der Server startet scheinbar nicht und eine Ausgabe in der Konsole hab ich auch nicht. Lässt sich jedenfalls nicht connecten.


:roll:

Den einzigen Unterschiede zwischen dem von dir geposteten Quelltext und dem Meinigen ist:
Delphi-Quellcode:
{$R *.lfm}
{$R *.dfm

:gruebel:

diesisteintester 17. Mai 2019 11:16

AW: Mit Server auf OnConnect reagieren wie?
 
{$R *.lfm} kommt von der Lazerus IDE, {$R *.dfm} von Delphi ... macht soweit ja mal keinen Unterschied.

Hab den Code auch mal getestet und der geht ...

wenn du sagst der "Server startet nicht", was passiert denn im Debugger?

Exception oder EA Violation ???

holger_barntrup 20. Mai 2019 05:23

AW: Mit Server auf OnConnect reagieren wie?
 
Liste der Anhänge anzeigen (Anzahl: 2)
Folgendes passiert wenn ich den Button1 drücke:

Anhang 51132

Anhang 51133

:?:

TiGü 20. Mai 2019 08:19

AW: Mit Server auf OnConnect reagieren wie?
 
Vielleicht nimmst du Delphi nur einmal im Jahr in die Hand.
Aber du bist seit 2007 hier angemeldet, d.h. du hast dich irgendwie in den letzten 12 Jahren mit Programmierung ab und an beschäftigt.

Da ist es wirklich nicht zuviel verlangt, mit dem Debugger und mithilfe eines Breakpoints im OnClick-Handler anzuhalten und Schritt für Schritt durch zu debuggen, bis der Fehler passiert.

Meine Glaskugel sagt: FServer ist nicht erzeugt worden und damit
Delphi-Quellcode:
nil
.:glaskugel:

holger_barntrup 20. Mai 2019 08:30

AW: Mit Server auf OnConnect reagieren wie?
 
Zitat:

Zitat von TiGü (Beitrag 1432575)
Vielleicht nimmst du Delphi nur einmal im Jahr in die Hand.
Aber du bist seit 2007 hier angemeldet, d.h. du hast dich irgendwie in den letzten 12 Jahren mit Programmierung ab und an beschäftigt.

Schlimmer noch, ich hab mich 2007 und 2008 um zwei kleine Projekte gekümmert die seit dem immer noch so laufen.
Dann hab ich bis ende letzten Jahres gar nichts mehr mit Delphi gemacht.
Das vielleicht mal als Anmerkung dazu.

hoika 20. Mai 2019 08:42

AW: Mit Server auf OnConnect reagieren wie?
 
Hallo,
wenn du das Projekt aus der IDE startest,
müsste er doch nach der Exception und F7 genau an der Problemstelle stehen.

holger_barntrup 20. Mai 2019 09:47

AW: Mit Server auf OnConnect reagieren wie?
 
Zitat:

Zitat von TiGü (Beitrag 1432575)
FServer ist nicht erzeugt worden und damit
Delphi-Quellcode:
nil

Genau so ist das, ich verstehe nur nicht warum.

holger_barntrup 20. Mai 2019 09:50

AW: Mit Server auf OnConnect reagieren wie?
 
Zitat:

Zitat von hoika (Beitrag 1432580)
Hallo,
wenn du das Projekt aus der IDE startest,
müsste er doch nach der Exception und F7 genau an der Problemstelle stehen.

Genau dann stehe ich bei:
Delphi-Quellcode:
FServer.Active := True;
Wenn ich dazu FServer überwache dann hat der den Wert (nil)

Wird also nicht erzeugt.

TiGü 20. Mai 2019 10:43

AW: Mit Server auf OnConnect reagieren wie?
 
Wo steht denn die Zeile
Delphi-Quellcode:
FServer := TIdTCPServer.Create(...);
?

holger_barntrup 21. Mai 2019 06:15

AW: Mit Server auf OnConnect reagieren wie?
 
Na dort wie in dem Beispiel aus #7

Mir geht es einfach darum zu verstehen was da nicht funktioniert wenn ich die Komponente zur Laufzeit erzeuge.
Wenn ich das 'IdTcpServer' auf der Form platziere funktioniert ja alles so wie geplant. :roll:

Schokohase 21. Mai 2019 06:25

AW: Mit Server auf OnConnect reagieren wie?
 
Kopiere doch einfach deinen aktuellen Quellcode der Form (pas und dfm) hier ins Forum damit wir auch eine Chance haben dir eine vernünftige Antwort zu geben.

holger_barntrup 21. Mai 2019 08:39

AW: Mit Server auf OnConnect reagieren wie?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Gerne doch

Klaus01 21. Mai 2019 09:10

AW: Mit Server auf OnConnect reagieren wie?
 
.. die FormCreate Methode ist die mit Deiner Form verkabelt?
D.h im Object Inspector zugewiesen?

Grüße
Klaus

holger_barntrup 21. Mai 2019 09:17

AW: Mit Server auf OnConnect reagieren wie?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier noch mal alles:

Klaus01 21. Mai 2019 09:20

AW: Mit Server auf OnConnect reagieren wie?
 
Liste der Anhänge anzeigen (Anzahl: 1)
siehe Anhang

TiGü 21. Mai 2019 09:21

AW: Mit Server auf OnConnect reagieren wie?
 
Zitat:

Zitat von Klaus01 (Beitrag 1432677)
.. die FormCreate Methode ist die mit Deiner Form verkabelt?
D.h im Object Inspector zugewiesen?

Nö, und das ist auch die Ursache für sein Problem.

holger_barntrup 21. Mai 2019 09:21

AW: Mit Server auf OnConnect reagieren wie?
 
Zitat:

Zitat von Klaus01 (Beitrag 1432677)
.. die FormCreate Methode ist die mit Deiner Form verkabelt?
D.h im Object Inspector zugewiesen?

Grüße
Klaus

Genau das war es..... :thumb:

holger_barntrup 21. Mai 2019 10:38

AW: Mit Server auf OnConnect reagieren wie?
 
Zitat:

Zitat von mjustin (Beitrag 1432354)
Beispielcode (mit Konsolenausgabe anstatt Listbox).

Hinweise: [LIST][*]das Erzeugen eines neuen Bindings ist nicht notwendig, standardmäßig wird beim Starten eines Indy TCP Servers bereits ein Binding erzeugt, mit IP 0.0.0.0. Im Code wird dann nur noch der Port gesetzt (über die DefaultPort-Property)

Und wie stell ich das denn an wenn ich eine bestimmte IP vorgeben will?
Mit
Delphi-Quellcode:
FServer.DefaultPort := 23; // Telnet Port
FServer.Bindings[0].IP := '172.16.101.111';
bekomm ich die Meldung "Argument ausserhalb des Bereichs" und die IP bleibt 0.0.0.0
In dem Beispiel oben im ersten Beitrag geht das, auch in dem mit den Komponenten auf der Form.
Ich glaub ich geb es bald auf mit dem erzeugen zur Laufzeit........

Klaus01 21. Mai 2019 10:54

AW: Mit Server auf OnConnect reagieren wie?
 
Delphi-Quellcode:
uses
  System.SysUtils, idTcpServer, idSocketHandle;

var
  fServer: TidTcpServer;
  binding: TidSocketHandle;
begin
  try
    fServer := TidTcpServer.create(nil);
    binding := fServer.Bindings.Add();
    binding.IP := '10.34.56.12';
    binding.Port := 23;
 except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
oder das böse with verwenden:
Delphi-Quellcode:
with fServer.bindings.add do
  begin
    ip := '10.34.56.12'
    port := 23;
  end;
Grüße
Klaus

holger_barntrup 22. Mai 2019 10:44

AW: Mit Server auf OnConnect reagieren wie?
 
Danke Klaus

:thumb:


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:50 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