Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Socket Komponente im XE4 <-> Indy TCPClient XE7 (https://www.delphipraxis.net/184106-socket-komponente-im-xe4-indy-tcpclient-xe7.html)

Alex_ITA01 26. Feb 2015 21:05


Socket Komponente im XE4 <-> Indy TCPClient XE7
 
Hallo zusammen,
ich habe folgendes Problem.

Ein kleines Programm schickt zwei Strings über eine TCPClient Komponente zu einem Server.
Das Programm liegt in zwei Varianten vor:

1)
XE4 Version mit der TCPClient Komponente aus der Unit "Web.Win.Sockets" (TTcpClient).
RemoteHost und RemotePort werden gesetzt.
Ich prüfe mit dem Befehl "Connect" ob ich mich verbinden kann und wenn ja, dann sende ich
die beiden Strings jeweils raus.
Dieses Programm funktioniert ohne Probleme.

2)
XE7 Version mit der TIdTCPClient Komponente der mitgelieferten Indy.
Grund: Es gibt die eingesetzte Komponente aus der XE4 Version nicht mehr.
Host und Port werden gesetzt.
Ich prüfe mit dem Befehl "if Connected" ob ich verbunden bin und wenn ja, dann sende ich
die beiden Strings jeweils raus. Wenn nein, rufe ich "Connect" auf und versuche dann nochmal auf "Connected" abzufragen.
Dieses Programm funktioniert auf meinem Rechner ohne Probleme.
Leider funktioniert das Programm auf zwei anderen Rechnern nicht wie bei mir und ich weiß nicht warum.
Es treten Exceptions beim Senden des jeweiligen Strings auf.
Fehlermeldung: Die Verbindung wurde erfolgreich geschlossen.
Bei jedem Sendebefehl.
Was mich wundert, bei mir auf dem Rechner funktioniert es (habe einem anderen Rechner die IP gegeben und das Programm ncat darauf gestartet und den entsprechenden Port geöffnet. Da kommt der String an. Keine Exceptions.
Bei zwei anderen Rechnern, entstehen die genannten Exceptions und es kommt auch kein String (Text) an.
Hättet ihr eine Idee dazu?

Source Ausschnitt Programm XE4:
Delphi-Quellcode:
SocketErr := False;
try
  try
    if Connect then
    begin
      try
        SendBuf(PAnsiChar(MyStr1)^, Length(MyStr1), 0);
      except
        on E:Exception do
        begin
          //Protokollierung E.Message
          SocketErr := True;
        end;
      end;

      try
        SendBuf(PAnsiChar(MyStr2)^, Length(MyStr2), 0);
      except
        on E:Exception do
        begin
          //Protokollierung E.Message
          SocketErr := True;
        end;
      end;
    end
    else
    begin
      //Protokollierung Connect nicht möglich
    end;
  except
    on E:Exception do
    begin
      //Protokollierung E.Message
      SocketErr := True;
    end;
  end;
finally
  if SocketErr then
  begin
    //Protokollierung SocketErr erkannt
  end;

  try
    Disconnect;
  except
    on E:Exception do
    begin
      //Protokollierung E.Message
    end;
  end;
end;
Source Ausschnitt Programm XE7:
Delphi-Quellcode:
SocketErr := False;
try
  try
    if not Connected then
    begin
      try
        //Protokollierung not Connected
        Connect;
      except
        on E:Exception do
        begin
          //Protokollierung E.Message
          SocketErr := True;
        end;
      end;
    end;
  except
    on E:Exception do
    begin
      //Protokollierung E.Message
      SocketErr := True;
    end;
  end;

  try
    if Connected then
    begin
      if Assigned(TCPClient.IOHandler) then
      begin
        try
          TCPClient.IOHandler.WriteLn(MyStr1);
        except
          on E:Exception do
          begin
            //Protokollierung E.Message
            //Hier kommt die Protokollierung "Die Verbindung wurde erfolgreich geschlossen."
            SocketErr := True;
          end;
        end;

        try
          TCPClient.IOHandler.WriteLn(MyStr2);
        except
          on E:Exception do
          begin
            //Protokollierung E.Message
            //Hier kommt die Protokollierung "Die Verbindung wurde erfolgreich geschlossen."
            SocketErr := True;
          end;
        end;
      end
      else
      begin
        //Protokollierung IOHandler nicht initialisiert
      end;
    end
    else
    begin
      //Protokollierung Connect nicht möglich
    end;
  except
    on E:Exception do
    begin
      //Protokollierung E.Message
      SocketErr := True;
    end;
  end;

finally
  if SocketErr then
  begin
    //Protokollierung SocketErr erkannt
  end;

  try
    Disconnect;
  except
    on E:Exception do
    begin
      //Protokollierung E.Message
    end;
  end;
end;
Ich hoffe ihr könnt mir da weiterhelfen.
Viele Grüße

mjustin 26. Feb 2015 21:50

AW: Socket Komponente im XE4 <-> Indy TCPClient XE7
 
Auf welches Objekt bezieht sich das Connected? Denn unerwartet ist, dass Connected so allein da steht. Wird das TCPClient Objekt über with angesprichen? Falls ja, dann muss auch IOHandler anstatt TCPClient.IOHandler kompilierbar sein.


Delphi-Quellcode:
if Connected then
    begin
      if Assigned(TCPClient.IOHandler) then
Daher wäre es hilfreich etwas mehr vom echten Code zu sehen.

Kommen die von der XE4 Komponente gesendeten Strings in allen drei Fällen auf dem Zielserver an?

Der Code für die XE7 Indy Komponente kann generell vereinfacht werden, da Connect eine Exception auslöst wird das anschliessende Abfragen von Connected nicht erreicht. (Der Code in dem das erste Connect ausgeführt wird ist auch im gezeigten Code nicht enthalten, es geht ja direkt mit if Connected los). Einige try - except können eingespart werden.

Der minimal notwendige Code wäre:

Delphi-Quellcode:
TCPClient := TIdTCPClient.Create;
try
  TCPClient.Host := AHost;
  TCPClient.Port := APort;
  try
    TCPClient.Connect;
    TCPClient.IOHandler.WriteLn(MyStr1);
    TCPClient.IOHandler.WriteLn(MyStr2);
    TCPClient.Disconnect;
  except
    on E: Exception do
    begin
      // log Exception
    end;
  end;
finally
  TCPClient.Free;
end;

Alex_ITA01 26. Feb 2015 21:57

AW: Socket Komponente im XE4 <-> Indy TCPClient XE7
 
Stimmt, eine Zeile im Code fehlt.
Nämlich das
Delphi-Quellcode:
with TCPClient do
Das steht ganz außen rum.
Du hast Recht, in der XE7 Variante habe ich vor dem IOHandler das TCPClient extra stehen. Das ist aber überflüssig und lässt sich auch compilieren.
Die vielen Exception Behandlungen habe ich nur reingemacht um festzustellen, wo es knallt.

Die XE4 Variante geht bei mir und den anderen beiden Rechnern ohne Probleme.
Nur die XE7 mit der eingesetzten Indy Komponente macht teilweise Probleme.
Was mich hat total wundert, warum bekomme ich beim "WriteLn" eine Exception die heißt, Verbindung erfolgreich geschlossen?
Ich wollte doch gar nicht schließen...
Hoffe ihr habt noch paar Ideen.

Viele Grüße

Edit für die XE7 Variante:
Ich habe die TIdTCPClient Komponente auf einem Formular sitzen und habe einen IOHandler als Komponente auch mit auf das Formular gesetzt. Dann habe ich bei der TCPClient Komponente den IOHandler entsprechend im Objektinspektor verknüpft.
Hat es vielleicht damit etwas zu tun?

Laut deinem Source weißt du ja gar keinen IOHandler zu!?

mjustin 26. Feb 2015 22:13

AW: Socket Komponente im XE4 <-> Indy TCPClient XE7
 
Zitat:

Zitat von Alex_ITA01 (Beitrag 1291675)
Ich habe die TIdTCPClient Komponente auf einem Formular sitzen und habe einen IOHandler als Komponente auch mit auf das Formular gesetzt. Dann habe ich bei der TCPClient Komponente den IOHandler entsprechend im Objektinspektor verknüpft.
Hat es vielleicht damit etwas zu tun?

Laut deinem Source weißt du ja gar keinen IOHandler zu!?

Indy erzeugt den Standard IOHandler selbst, er muss nicht zugewiesen werden. (Ausnahmen sind SSL-IOHandler.)

Wenn die Gegenseite die Verbindung "sauber" schliesst, und danach ein Lesezugriff (oder Schreibzugriff) aus dem IOHandler auf die Verbindung stattfindet, wird Indy dies mit einer Exception melden. Was genau geschieht läßt sich man am einfachsten im Debugger nachvollziehen.

Alex_ITA01 27. Feb 2015 08:10

AW: Socket Komponente im XE4 <-> Indy TCPClient XE7
 
Delphi-Quellcode:
  try
    TCPClient.Connect;
    TCPClient.IOHandler.WriteLn(MyStr1);
    TCPClient.IOHandler.WriteLn(MyStr2);
    TCPClient.Disconnect;
  except
    on E: Exception do
    begin
      // log Exception
    end;
  end;
Habe es jetzt mal genauso hintereinander weg geschrieben wie du und jetzt bekomme ich auf dem Rechnern wo es vorher nicht ging folgende Exception:

Exception: Verbindung besteht bereits.

Allerdings erst beim zweiten Sendeversuch.
Ich vermute der Server trennt die Verbindung nicht richtig oder?

Mit der XE4 Komponente funktioniert es allerdings. Die verhält sich also irgendwie anders.

Grüße

Der schöne Günther 27. Feb 2015 09:46

AW: Socket Komponente im XE4 <-> Indy TCPClient XE7
 
Was für ein Zufall, die gleiche Frage hatte ich gestern (ebenfalls XE7) auch: Ich sage auf einem
Delphi-Quellcode:
TidTCPClient
Delphi-Quellcode:
Disconnect()
und danach liefert
Delphi-Quellcode:
Connected()
immer noch
Delphi-Quellcode:
True
.

Ich bin da kein Profi, weiß aber noch, dass bei TCP das Schließen der Verbindung im gegenseitigen Abmelden besteht. Ich werde also wahrscheinlich irgendein Event benutzen müssen wann die Verbindung wirklich zu ist.

Alex_ITA01 27. Feb 2015 10:31

AW: Socket Komponente im XE4 <-> Indy TCPClient XE7
 
Dann gehts nicht nur mir so ;-)

Mich wundert nur, dass der XE4 Source funktioniert, ohne dass ich an dem Server etwas geändert habe. Da scheint also die Verbindung "sauber" getrennt zu werden...

mjustin 27. Feb 2015 12:50

AW: Socket Komponente im XE4 <-> Indy TCPClient XE7
 
Zitat:

Zitat von Alex_ITA01 (Beitrag 1291698)
Mich wundert nur, dass der XE4 Source funktioniert, ohne dass ich an dem Server etwas geändert habe. Da scheint also die Verbindung "sauber" getrennt zu werden...

Den aktuellen Verbindungsstatus kann man auf Systemebene mit netstat oder TCPView kontrollieren. Als erste Maßnahme um halboffene Verbindungen bei zweiter und weiterer Verwendung, auszuschliessen würde ich die TIdTCPClient Komponente nicht auf dem Formular ablegen, sondern nur im Source dynamisch erzeugen (wie in meinem Beispiel).

hathor 27. Feb 2015 13:06

AW: Socket Komponente im XE4 <-> Indy TCPClient XE7
 
Zitat:

Zitat von Alex_ITA01 (Beitrag 1291672)
...
XE7 Version mit der TIdTCPClient Komponente der mitgelieferten Indy.
Grund: Es gibt die eingesetzte Komponente aus der XE4 Version nicht mehr.
...
Ich hoffe ihr könnt mir da weiterhelfen.
Viele Grüße

Die Komponente ist vorhanden, aber nicht installiert.
Man findet sie unter ...SAMPLES\Object Pascal\VCL\InetWinSockets.
Beschreibung:
http://docwiki.embarcadero.com/CodeE...Sockets_Sample

Alex_ITA01 27. Feb 2015 13:15

AW: Socket Komponente im XE4 <-> Indy TCPClient XE7
 
Danke, habe ich gar nicht gewusst, dass die noch irgendwo schlummern ;-)

Werde das auch mal mit der dynamischen Erzeugung probieren.

Viele Grüße


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