Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi ClientSocket bekommt keine Verbindung (https://www.delphipraxis.net/172461-clientsocket-bekommt-keine-verbindung.html)

UliBru 5. Jan 2013 13:51

ClientSocket bekommt keine Verbindung
 
Habe ein für mich unverständliches Problem. Siehe Code-Snippet

Delphi-Quellcode:
procedure TMainForm.Button1Click(Sender: TObject);
begin
  ServerSocket1.Port := 8078;
  ServerSocket1.Open;
  if (ServerSocket1.Port = 8078) and (ServerSocket1.Active) then //Server aktiv ??
  begin
    ClientSocket1.Port := 8078;
    ClientSocket1.Address := '127.0.0.1';
    ClientSocket1.Open;
    if ClientSocket1.Active then // <------------------- hier tut sich nichts
      n := ClientSocket1.Socket.SendText(AnsiString('Test'));
    ClientSocket1.Close;
  end;
end;
Ich will für ein Miniprogramm (eigentlich ohne Fenster) die guten alten TClientSocket und TServerSocket verwenden.
Bekomme aber keine Verbindung. Nun hab ich mal alles auf o.g. Schnipsel reduziert.
Der Server wird geöffnet, der Port zugewiesen.
Das Öffnen des Clients klappt nicht, das ClientSocket1.Active bleibt immer false.

Woran kann das liegen, was muss ich evtl. tun ?

Grüsse,
Uli

sx2008 5. Jan 2013 14:15

AW: ClientSocket bekommt keine Verbindung
 
Also ich würde Server und Client getrennt voneinander entwickeln.
Dabei sollte zuerst der Server funktionieren bevor man sich an den Client macht.
Windows hat standardmässig das Programm telnet.exe an Bord mit dem man den Server testen kann.
(manchmal muss man den Telnet-Client nachinstallieren)
Erst wenn dieser Test erfolgreich ist, lohnt es sich mit dem Client zu beginnen.
Der Aufruf in der Eingabeaufforderung lautet:

Code:
C:\> telnet localhost 8078
Entweder kommt eine Verbindung zustande oder nicht.
Falls nicht gibt es ein Problem im Server.

UliBru 5. Jan 2013 15:28

AW: ClientSocket bekommt keine Verbindung
 
Ja, ich hatte zuerst auch den Server unabhängig vom Client geschrieben.
Und wenn ich beim Sever mit
Delphi-Quellcode:
telnet localhost 8078
teste, bekomme ich auch eine Verbindung inkl. Anzeige des gesendeten Textes im Server. Das klappt also.

Meine eigentliche Anwendung (testweise arg geschrumpft) ist
Delphi-Quellcode:
program ACSendCommand;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils, System.Win.ScktComp;

var
  Client: TClientSocket;

begin
  Client := TClientSocket.Create(nil);
  Client.Host := 'localhost';
  Client.Port := 8078;
  Client.Open;
  if Client.Active then // <-----------------------wird nicht aktiv
    Client.Socket.SendText(AnsiString('Test'));
  Client.Close;
  Client.Free;
end.

Ich hab da nun ebenfalls als Hostadresse localhost vorgegeben. Es klappt genausowenig wie mit 127.0.0.1 oder der richtigen IP.
Also scheint da was falsch zu sein im Gegensatz zu Telnet.
Auch ein Senden ohne Abfrage auf den aktiven Client bringt nichts.

Beim Server wird dieselbe ScktComp verwendet. Delphi ist XE2.

sx2008 5. Jan 2013 17:06

AW: ClientSocket bekommt keine Verbindung
 
Unit ScktComp.pas in Projektverzeichnis kopieren und ins Projekt aufnehmen.
(Ggf. muss uses System.Win.ScktComp -> uses ScktComp geändert werden)
Danach kann man auf
Delphi-Quellcode:
if Client.Active then
einen Breakpoint setzen und per Einzelschritt nachforschen woran es klemmt.

Ausserdem sollte man testen, ob das Problem vielleicht nur bei einer Konsolenanwendung besteht.
Sockets melden Ereignisse über Windows Messages; da es bei Konsolenanwendungen keine Messageloop gibt wäre es denkbar, dass dies ein Problem darstellt.

Aphton 5. Jan 2013 18:38

AW: ClientSocket bekommt keine Verbindung
 
Probiers mal so:
Delphi-Quellcode:
  Client.Open;
  Sleep(1000); // 1 sek
  Application.ProcessMessages;
  if Client.Active then // <-----------------------wird nicht aktiv
Ich glaube, die Komponente ist standardmäßig non-blocking - dh. beim Verbindungsaufbau wird das Programm fortgesetzt. Da liefert dir Active false, da evt. noch nicht erfolgreich verbunden wurde.
Das dauert im Schnitt einige Sekunden...

mjustin 5. Jan 2013 19:35

AW: ClientSocket bekommt keine Verbindung
 
Zitat:

Zitat von sx2008 (Beitrag 1197808)
Sockets melden Ereignisse über Windows Messages; da es bei Konsolenanwendungen keine Messageloop gibt wäre es denkbar, dass dies ein Problem darstellt.

Und wie funktioniert dann telnet.exe? :)

Indy und Synapse TCP Clients funktionieren problemlos in Konsole Anwendungen, nur die alten TClient/TServerSockets (asynchron) und andere asynchrone Komponenten wie ICS benötigen die Windows Message Loop, um Gegensatz zu Indy und Synapse (die dadurch auch leichter auf anderen Betriebssystemen einsetzbar sind).

Oft wird aber hier in diesem Zusammenhang 'Sockets' gesagt, aber damit ist dann nicht die allgmein bekannten TCP/IP Sockets, sondern speziell die alten Delphi TClientSocket / TServerSocket Komponenten gemeint.

sx2008 5. Jan 2013 23:21

AW: ClientSocket bekommt keine Verbindung
 
Zitat:

Zitat von mjustin (Beitrag 1197852)
Zitat:

Zitat von sx2008 (Beitrag 1197808)
Sockets melden Ereignisse über Windows Messages; da es bei Konsolenanwendungen keine Message Loop gibt wäre es denkbar, dass dies ein Problem darstellt.

Und wie funktioniert dann telnet.exe? :)

Windows Sockets können Windows Messages versenden (WSAAsyncSelect), müssen aber nicht.
Und Konsolenanwendungen können ein unsichtbares Window + einen Thread erzeugen um die Messages zu empfangen und abzuarbeiten.
Wie das in telnet.exe läuft, weiss ich nicht aber es ein Aspekt der bei asynchronen Sockets beachtet werden sollte.

Zacherl 6. Jan 2013 04:37

AW: ClientSocket bekommt keine Verbindung
 
Genau das hier trifft zu:
Zitat:

Zitat von Aphton (Beitrag 1197842)
Ich glaube, die Komponente ist standardmäßig non-blocking - dh. beim Verbindungsaufbau wird das Programm fortgesetzt. Da liefert dir Active false, da evt. noch nicht erfolgreich verbunden wurde.
Das dauert im Schnitt einige Sekunden...

Als schnelle Lösung würde ich vorschlagen die Eigenschaft ClientType des Sockets auf ctBlocking zu setzen. Ich sehe bei einer Konsolenanwendung sowieso keinen großen Vorteil in non blocking Sockets.

UliBru 6. Jan 2013 09:48

AW: ClientSocket bekommt keine Verbindung [gelöst]
 
Zitat:

Zitat von Zacherl (Beitrag 1197927)
Als schnelle Lösung würde ich vorschlagen die Eigenschaft ClientType des Sockets auf ctBlocking zu setzen. Ich sehe bei einer Konsolenanwendung sowieso keinen großen Vorteil in non blocking Sockets.

Das muss ich nochmal testen. Klingt logisch.
In der Zwischenzeit hab ich es mit Indy getestet und das klappt. Never touch a running system ...

Delphi-Quellcode:
  IdTCPClient1 := TIdTCPClient.Create(nil);
  try
    IdTCPClient1.Host := '127.0.0.1';
    IdTCPClient1.Port := 8078;
    IdTCPClient1.Connect;
    if IdTCPClient1.Connected then
    begin
      IdTCPClient1.IOHandler.Write(s);
      IdTCPClient1.Disconnect;
    end;
  except
    on E: Exception do ;
  end;
  IdTCPClient1.Free;

mjustin 6. Jan 2013 10:22

AW: ClientSocket bekommt keine Verbindung [gelöst]
 
Zitat:

Zitat von UliBru (Beitrag 1197938)
In der Zwischenzeit hab ich es mit Indy getestet und das klappt.

Delphi-Quellcode:
  IdTCPClient1 := TIdTCPClient.Create(nil);
  try
    IdTCPClient1.Host := '127.0.0.1';
    IdTCPClient1.Port := 8078;
    IdTCPClient1.Connect;
    if IdTCPClient1.Connected then
    begin
      IdTCPClient1.IOHandler.Write(s);
      IdTCPClient1.Disconnect;
    end;
  except
    on E: Exception do ;
  end;
  IdTCPClient1.Free;

Man kann das if IdTCPClient1.Connected then ... weglassen, denn wenn der Verbindungsaufbau mit IdTCPClient1.Connected scheitert, wird eine Exception ausgelöst. Die Zeile mit der Abfrage auf Connected würde also nie erreicht.

Sicherheitshalber würde ich das Free in einem finally Block platzieren.


Delphi-Quellcode:
  IdTCPClient1 := TIdTCPClient.Create(nil);
  try
    IdTCPClient1.Host := '127.0.0.1';
    IdTCPClient1.Port := 8078;
    try
      IdTCPClient1.Connect;
      IdTCPClient1.IOHandler.Write(s);
      IdTCPClient1.Disconnect;
    except
      on E: Exception do
      begin
        Log(E);
        raise;
      end;
    end;
  finally
    IdTCPClient1.Free;  
  end;

UliBru 6. Jan 2013 11:50

AW: ClientSocket bekommt keine Verbindung
 
Ich hab nun
Delphi-Quellcode:
Client.ClientType := ctBlocking
getestet und damit klappt es auch. Das was der ursächliche Grund.
Da sich mit TClientSocket ein kleineres Programm ergibt als mit TIdTCPClient verwende ich nun doch wieder das TClientSocket.

Das Programm sieht nun so aus:
Delphi-Quellcode:
  Client := TClientSocket.Create(nil);
  try
    Client.Host := '127.0.0.1';
    Client.Port := 8078;
    Client.ClientType := ctBlocking;
    try
      Client.Open;
      Client.Socket.SendText(AnsiString(s));
      Client.Close;
    except
      on E: Exception do; //ignore, do nothing
    end;
  finally
    Client.Free;
  end;

Morphie 6. Jan 2013 12:20

AW: ClientSocket bekommt keine Verbindung
 
Ähm, warum nutzt du nicht einfach das Event OnConnect dafür?
Depending on the service, this may be the point when the socket should start reading or writing over the connection.

Aphton 6. Jan 2013 13:52

AW: ClientSocket bekommt keine Verbindung
 
Eine kleine Bemerkung, die du unbedingt durchlesen solltest, falls du bei den Nativen Komponenten bleibst (TClientsocket/TServersocket).
Es kann sein, dass es diese Problem bei Indy nicht gibt, da Indy das selbst auch intern macht - kenn mich mit Indies ned so aus.

UliBru 6. Jan 2013 13:55

AW: ClientSocket bekommt keine Verbindung
 
Zitat:

Zitat von Morphie (Beitrag 1197957)
Ähm, warum nutzt du nicht einfach das Event OnConnect dafür?
Depending on the service, this may be the point when the socket should start reading or writing over the connection.

Ähm, gute Idee. Werde ich gern auch mal testen.
Es scheint mir als ob man nur durch Trial & Error lernt. Die Beschreibung einer Komponente mit den jeweiligen Methoden und Eigenschaften besagt ja nicht direkt etwas darüber, WIE man das nun richtig einsetzt. Und dann studiert man ja auch nicht jede Methode bis ins Letzte. Also schaut man nach Beispielen. Und bei den Beispielen hier im Forum, oder http://www.delphi-treff.de/tutorials...programmierung als auch z.B. about.com und woanders habe ich es so vorgefunden, wie ich es denn realisiert habe. Wobei das
Delphi-Quellcode:
ctBlocking
in keinem der Beispiele vorkam. Oder, dass man die Abfrage auf aktiv nicht braucht, weil Exception. Das OnConnect ist auch nicht aufgetaucht, bis eben auf Deinen Hinweis.

Zacherl 6. Jan 2013 15:43

AW: ClientSocket bekommt keine Verbindung
 
Zitat:

Zitat von mjustin (Beitrag 1197942)
Man kann das if IdTCPClient1.Connected then ... weglassen, denn wenn der Verbindungsaufbau mit IdTCPClient1.Connected scheitert, wird eine Exception ausgelöst. Die Zeile mit der Abfrage auf Connected würde also nie erreicht.

Sicherheitshalber würde ich das Free in einem finally Block platzieren.

Dies gillt ebenfalls für die normale TClientSocket Komponente. Open() löst eine Exception aus, fals die Verbindung fehlschlägt.

Zitat:

Zitat von Morphie (Beitrag 1197957)
Ähm, warum nutzt du nicht einfach das Event OnConnect dafür?

Ich bin mir ziemlich sicher, dass dieses Event nur für die non blocking Variante funktioniert und bei dieser benötigt man wieder zwingend eine Message Queue (und ein Window?).

Zitat:

Zitat von Aphton (Beitrag 1197970)
Eine kleine Bemerkung, die du unbedingt durchlesen solltest, falls du bei den Nativen Komponenten bleibst (TClientsocket/TServersocket).
Es kann sein, dass es diese Problem bei Indy nicht gibt, da Indy das selbst auch intern macht - kenn mich mit Indies ned so aus.

Pakettrennung muss sowohl bei Indy, als auch bei den normalen Socket Komponenten per Hand implementiert werden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:46 Uhr.

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