Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Indy Socked-Fehler 10093 (https://www.delphipraxis.net/204744-indy-socked-fehler-10093-a.html)

Int3g3r 24. Jun 2020 12:54

Delphi-Version: 10.1 Berlin

Indy Socked-Fehler 10093
 
Guten Tag,

Ich habe eine Programm geschrieben das nur aus einer Unit und einem From besteht.
Beim Starten wird das From angezeigt.
Beim erstellen des Froms wird im OnActivate folgendes aufgerufen:

Delphi-Quellcode:
procedure THeaderFooterForm.FormActivate(Sender: TObject);
var i : integer;
begin
   if not assigned(server) then
      server := TServer.Create('127.0.0.1',25222,true);
   i := 0;
end;
Die TServer Klasse ist in der Unit definiert wie folgt:
Delphi-Quellcode:
type
   TServer = class(TObject)
      constructor Create(_IP:String; _Port:Word; _Start:Boolean); overload;
      destructor Destroy; override;
      procedure BeforeDestruction; override;
   private
      tcpServer: TIdTCPServer;
      recievedData : TStringList;
      procedure fillPersonData;
      procedure tcpServerExecute(AContext: TIdContext);
   public

   end;

   var
   personData: TPersonData;
   server : TServer;

implementation

procedure TServer.BeforeDestruction;
begin
   Stop;
   inherited BeforeDestruction;
end;

constructor TServer.Create(_IP:String; _Port:Word; _Start:Boolean);
begin
   inherited Create;
   tcpServer := TIdTCPServer.Create(nil);
   recievedData := TStringList.Create;
   tcpServer.Bindings.Clear;
   tcpServer.Bindings.Add;
   tcpServer.Bindings.Items[0].IP := _IP;
   tcpServer.Bindings.Items[0].Port := _Port;
   tcpServer.Bindings.Items[0].IPVersion := Id_IPv4; // uses IdGlobal
   tcpServer.OnExecute := tcpServerExecute;
   tcpServer.Active := _Start;
end;

destructor TServer.Destroy;
begin
   if Assigned(tcpServer) then
         FreeAndNil(tcpServer);
   if Assigned(recievedData) then
         FreeAndNil(recievedData);
end;
Wie zu sehen ist starte ich den tcpServer im constructor, dies funktioniert auch wie gewünscht.
Sobald ich nun aber das Form schliesse und tcpServer.Active := true ist erhalte ich eine Socket exception: 'Socket-Fehler#10093'
Diese erhalte ich aber nur wenn ich das Projekt im Debug-Modus starte. Ich erhalte keine exception wenn ich die exe direkt starte.

Da ich mir beim verwenden von Konstruktoren und Destruktoren noch nicht sicher bin ob dies korrekt ist bitte ich euch diese zuerst zu überprüfen.
Ich gehe davon aus das der tcpServer nicht korrekt freigegeben wird und daher auch der Socket.

Besten Dank für die Hilfe,
Int3g3r


EDIT:

Wenn ich im Form beim OnClose den server freigebe ist die Fehlermeldung weg.
Delphi-Quellcode:
procedure THeaderFooterForm.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
    FreeAndNil(server);
end;
Daher müsste ich beim Konstructor einen Owner setzen ist dies korrekt ?
Somit würde beim zerstören des Form auch die Unit freigegeben.
Kann mir dazu jemand ein Beispiel machen ?

.... Hmm habe gerade bemerkt das ein Owner nur bei einem TForm gesetzt werden kann.
TObject bietet dies nicht an. Ich möchte erreichen das das Objekt "server" automatisch zerstört wird
wenn ich das Form schliesse. Ohne ein manuelles FreeAndNil.

Der schöne Günther 24. Jun 2020 14:05

AW: Indy Socked-Fehler 10093
 
Zitat:

Zitat von Int3g3r (Beitrag 1468170)
Ich möchte erreichen das das Objekt "server" automatisch zerstört wird
wenn ich das Form schliesse. Ohne ein manuelles FreeAndNil.

Die paar Buchstaben wirst du noch tippen müssen. Theoretisch könntest du dir mit "Smart Pointern" was dafür basteln, aber das führt zu weit weg von der eigentlichen Frage.

Keep it simple, stupid. Wenn dein Formular deinen TServer im OnCreate erzeugt, zerstöre es doch auch im OnDestroy. Wenn du es im Konstruktor erzeugst, zerstöre es doch auch im Destruktor. Will damit auch sagen: OnActivate ist ein sehr merkwürdiger Ort. Was spricht gegen OnCreate oder den Konstruktor des Formulars?


Socket Error Codes wie diesen kannst du nachschlagen:
https://docs.microsoft.com/en-us/win...-error-codes-2
10093 steht für:
Zitat:

Successful WSAStartup not yet performed.
Either the application has not called WSAStartup or WSAStartup failed. The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks), or WSACleanup has been called too many times.

Wenn du im Debugger anhälst siehst du auch was genau Sache ist:
Die Exception kommt aus dem Thread deines TCP-Servers. Dem fliegt um die Ohren dass jetzt grade (im Hauptthread) durch den
Delphi-Quellcode:
finalization
-Abschnitt der Indy-Unit IdStackWindows die Methode UninitializeIPHelperAPI aufgerufen wurde. Die ruft die Windows-Routine WSACleanup auf um alles jetzt endgültig zu Ende zu bringen. Dein Server allerdings läuft immer noch (da du keine Lust hattest ihn freizugeben). Deshalb läuft der jetzt auf einen Fehler der dir im Debugger angezeigt wird.

Ohne Debugger siehst du das nicht da die Anwendung eh schon am Herunterfahren ist, ich glaube zu dem Zeitpunkt gibt es auch keine VCL mehr die dir großartig etwas anzeigen könnte. Außerdem tritt der Fehler ja nicht im Hauptthread, sondern in einem Neben-Thread von Indy auf.

Int3g3r 24. Jun 2020 14:56

AW: Indy Socked-Fehler 10093
 
Zitat:

Die paar Buchstaben wirst du noch tippen müssen.
Danke für die Hilfe und erklärungen Günther!

Gruss Int3g3r


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