AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

IdTCPServer Threadproblem

Ein Thema von Nakaron · begonnen am 24. Aug 2007 · letzter Beitrag vom 24. Aug 2007
Antwort Antwort
Nakaron

Registriert seit: 19. Mär 2004
28 Beiträge
 
Delphi 2007 Professional
 
#1

IdTCPServer Threadproblem

  Alt 24. Aug 2007, 12:38
Hallo zusammen,

ich bin gerade dabei eine Client->Server->Client Anwendung zuschreiben. Mein großes Problem ist dabei, sobald ein Client sich einmal mit dem Server verbunden hat und dann wieder disconnected und ich den Server beenden möchte, dass diese Serveranwendung einfriert und ich diese nur noch über den Taskmanager beenden kann.

Meine Einzige Vermutung liegt nun darin, dass die ThreadConnections nicht ordentlich geschlossen werden.
Anbei mal die wichtigsten Codesnippets aus meinem Projekt:

Delphi-Quellcode:
type
  PClient = ^TClient;
  TClient = record // Objekt enthält Daten vom Client
                IP : String[15]; { IP Adressse des Users }
                UserID : String[10]; { Benutzer ID in der DB }
                UserName : String[100]; { Benutzername }
                Connected : TDateTime; { Zeitstempel des Verbindungsaufbaus }
                Thread : Pointer; { Pointer zum IdContext-Thread }
              end;
.
.
.

var
  frmMain : TfrmMain;
  Clients : TThreadList;
.
.
.

procedure TfrmMain.TCPServerConnect(AContext: TIdContext);
var
  NewClient: PClient;
begin
  GetMem(NewClient, SizeOf(TClient));

  NewClient.IP := AContext.Connection.Socket.Binding.PeerIP;
  NewClient.Connected := Now;
  NewClient.Thread := AContext;

  AContext.Data:=TObject(NewClient);

  try
    Clients.LockList.Add(NewClient);
  finally
    Clients.UnlockList;
  end;
end;

procedure TfrmMain.TCPServerDisconnect(AContext: TIdContext);
var
  ActClient: PClient;
  vI : Integer;
begin
  ActClient := PClient(AContext.Data);
  try
    Clients.LockList.Remove(ActClient);
    for vI:=0 to lvConnectedClients.Items.Count-1 do
      if(PClient(lvConnectedClients.Items[vI].Data)^.IP = ActClient.IP) then
      begin
        Dispose(lvConnectedClients.Items[vI].Data);
        lvConnectedClients.Items[vI].Delete;
      end;
    grpConnectedClients.Caption := 'Angemeldete Clients (' + IntToStr(lvConnectedClients.Items.Count) + ' Benutzer)';
  finally
    Clients.UnlockList;
  end;

  FreeMem(ActClient);
  AContext.Data := nil;
end;

procedure TfrmMain.TCPServerExecute(AContext: TIdContext);
var
  Data: String;
  vI: Integer;
  ActClient : PClient;
begin
  Data := AContext.Connection.Socket.ReadLn;
  Data := decodeStr(Data);

  ActClient := PClient(AContext.Data);

  if(Pos('[CMClient]AuthMe', Data) > 0) then
  begin
    addToLog('Authentifizierungsanfrage von: ' + AContext.Binding.PeerIP, 0, [], 8);
    doSELECT('SELECT usr_id, usr_loginName FROM cm_user WHERE usr_loginName = "' + GetTagData('Username', Data) + '" AND usr_loginPassword = "' + GetTagData('Password', Data) + '" LIMIT 1');

    if(Query.RecordCount <> 0) then
    begin
      addToLog('Authentifizierung erfolgreich.', 15, [], 8, clGreen);
      ActClient.UserID := Query.FieldByName('usr_id').AsString;
      ActClient.UserName:= Query.FieldByName('usr_loginName').AsString;
      lvConnectedClients.AddItem(Query.FieldByName('usr_loginName').AsString, Pointer(ActClient));
      lvConnectedClients.Items[lvConnectedClients.Items.Count-1].SubItems.Add('');

      AContext.Connection.Socket.WriteLn(encodeStr('[CMServer]Verify<Reason>Success</Reason>'));
    end else
    begin
      addToLog('Authentifizierung fehlgeschlagen.', 15, [], 8, clRed);
      AContext.Connection.Socket.WriteLn(encodeStr('[CMServer]Verify<Reason>Failed</Reason><ErrorMsg>Falsche Benutzer/Passwort Kombination!</ErrorMsg>'));
    end;
    exit;
  end;
end;
Ich bin bereits seit Tagen auf der Suche nach einer Lösung. Ich hoffe ihr könnt mir weiterhelfen.

Vielen Dank schon einmal im voraus.

Viele Grüße
Nakaron
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von DataCool
DataCool

Registriert seit: 10. Feb 2003
Ort: Lingen
909 Beiträge
 
Delphi 10.3 Rio
 
#2

Re: IdTCPServer Threadproblem

  Alt 24. Aug 2007, 12:53
Hi Nakaron,

ich konnte leider beim ersten drüber schauen keinen Fehler finden.
Allerdings kann ich Dir sagen das ich bei Delphi 2007 + Indy10 NICHT
diese Probleme habe.

Bei mir sieht die Struktur zwar etwas anders aus, aber vom Prinzip genau der gleiche Ablauf,
nur das ich die Verification des Clients schon im OnConnect Ereignis behandle und nur
ein TClient Object erzeuge wenn die Anmeldung/verifizierung erfolgreich war.

Bei Deiner Lösung wird ja bei jedem Port-Scan ein Client Object erzeugt ...

Ich schaue nachher aber nochmal genauer über Deinen Code,

*Edit*

Denke habe die Ursache gefunden, Dein Client schickt nie ein "Disconnect/QUIT" Commando zum Server !
Somit kann der Server gar nicht feststellen, wann der Client sich disconnecten will.

Mache bitte mal folgendes :
- Dein ganzes Handling für die Client-Verifizierung bitte in das OnConnect !
- Wenn beim OnConnect kein gültiges Login gesendet wird, die Connection sofort wieder schliessen
- Erst nach erfolgreicher Anmeldung TClient erzeugen und in .Data ablegen

- Im OnExecute nut Commandos behandeln die nach dem Login erfolgen,
aber dort muss es auf jeden Fall ein Kommando wie z.B. "QUIT" geben,
wenn der SErver dieses Commando vom Client erhält muss er die Connection schliessen

- Im OnDisconnect musst Du prüfen, ob im .Data Daten vorhanden sind
If Assigned(....Data) then begin
- ansonsten .Data = nil war es nur ein Port-Scan

Greetz DataCool
Der Horizont vieler Menschen ist ein Kreis mit Radius Null, und das nennen sie ihren Standpunkt.
  Mit Zitat antworten Zitat
Nakaron

Registriert seit: 19. Mär 2004
28 Beiträge
 
Delphi 2007 Professional
 
#3

Re: IdTCPServer Threadproblem

  Alt 24. Aug 2007, 13:09
Hi DataCool,

danke erstmal für deine schnelle Antwort.
Die Clientverifizierung kann ich leider nicht in das OnConnect packen, da der Client erst nach dem Connect die vom Clientbenutzer eingegebenen Logindaten an den Server sendet. Beim Server wird dann im OnExecute geprüft ob die Logindaten mit denen, welche sich in einer MySQL Datenbank befinden, übereinstimmen.

Viele Grüße
Nakaron
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von DataCool
DataCool

Registriert seit: 10. Feb 2003
Ort: Lingen
909 Beiträge
 
Delphi 10.3 Rio
 
#4

Re: IdTCPServer Threadproblem

  Alt 24. Aug 2007, 13:13
Hi,

Zitat:
Die Clientverifizierung kann ich leider nicht in das OnConnect packen, da der Client erst nach dem Connect die vom Clientbenutzer eingegebenen Logindaten an den Server sendet. Beim Server wird dann im OnExecute geprüft ob die Logindaten mit denen, welche sich in einer MySQL Datenbank befinden, übereinstimmen.
Ich sehe bei Deinem Code absolut kein Problem den Verifizierungscode ins OnConnect zu packen.
Du kannst im OnConnect des Servers auch ein ReadLn machen

Greetz DAtaCool
Der Horizont vieler Menschen ist ein Kreis mit Radius Null, und das nennen sie ihren Standpunkt.
  Mit Zitat antworten Zitat
Nakaron

Registriert seit: 19. Mär 2004
28 Beiträge
 
Delphi 2007 Professional
 
#5

Re: IdTCPServer Threadproblem

  Alt 24. Aug 2007, 13:28
Ok, daran hab ich nicht gedacht

Hab nun alles eingebaut was du mir geraten hast. Eine Frage habe ich dennoch:

Was ist, wenn die Verbindung vom Client einfach abbricht? Dann habe ich doch wieder das selbe Problem ...


Viele Grüße
Nakaron
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von DataCool
DataCool

Registriert seit: 10. Feb 2003
Ort: Lingen
909 Beiträge
 
Delphi 10.3 Rio
 
#6

Re: IdTCPServer Threadproblem

  Alt 24. Aug 2007, 13:34
Hi,

das löse ich immer so, indem ich dem Client Object eine Eigenschaft
"LastAction" TDateTime gebe.
Diese immer aktualisieren wenn was im OnExecute vom Client kommt.

Dann machst Du Dir einen seperaten Timer oder Thread(eleganter) der in einem bestimmten Intervall
alle Client objekte durchgeht schaut wann die letzte Action war und wenn diese zu lange her ist,
dann versuchst Du in the Connection des Clients ein z.B. "NOOP" zu schreiben.
Wenn der Client mittlerweile disconnected ist, dann merkt das jetzt auch der Server
Wenn der Client noch verbunden ist, passiert nichts ausser das beim Client ein "NOOP" ankommt,
das sollte natürlich gehandelt werden.

Greetz DAtaCool
Der Horizont vieler Menschen ist ein Kreis mit Radius Null, und das nennen sie ihren Standpunkt.
  Mit Zitat antworten Zitat
Nakaron

Registriert seit: 19. Mär 2004
28 Beiträge
 
Delphi 2007 Professional
 
#7

Re: IdTCPServer Threadproblem

  Alt 24. Aug 2007, 13:37
Vielen Dank DataCool. Du hast mir sehr geholfen.

Das Problem ist nun endlich gefixt. Bin dir echt was Schuldig

Viele Grüße
Nakaron
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von DataCool
DataCool

Registriert seit: 10. Feb 2003
Ort: Lingen
909 Beiträge
 
Delphi 10.3 Rio
 
#8

Re: IdTCPServer Threadproblem

  Alt 24. Aug 2007, 13:41
Hi,

kein Problem, Indy ist mein Spezial Gebiet

Werd bestimmt mal die ein oder andere Frage in nem anderem Bereich haben

Bis dahin frohes Schaffen,

Greetz DataCool
Der Horizont vieler Menschen ist ein Kreis mit Radius Null, und das nennen sie ihren Standpunkt.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01: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