INDY - problem serwera TCP przy deaktywacji

0

Witam.

Łącze dwa programiki przez TCP. Programy muszą czodzić bardzo stabilnie a jest pewien problem. 

Programik klienta łączy się z serwerem przesyła dane i rozłącza się dopiero po 5s (tak musi działać). Jeżeli w czasie gdy client jest podłączony ktoś zechce wyłączyć serwer to wyświetli mu się błąd ("Terminate Thread Timeout" a w trybie debagowania wyświetla się bład "... raised exception class EIdClosedSocket with message 'Disconnect' " . To samo sie dzieje przy próbie deaktywacji serwera.

Jak bezpiecznie wyłączyć serwer lub go deaktywować?

A to fragment kodu servera:


//aktywacja/deaktywacja
procedure TServerFrmMain.CBServerActiveClick(Sender: TObject);
begin
        Server.Active:=CBServerActive.Checked;
end;



procedure TServerFrmMain.ServerConnect(AThread: TIdPeerThread);
var
  NewClient: PClient;

begin
  GetMem(NewClient, SizeOf(TClient));

  NewClient.DNS         := AThread.Connection.LocalName;
  NewClient.Connected   := Now;
  NewClient.LastAction  := NewClient.Connected;
  NewClient.Thread      :=AThread;

  AThread.Data:=TObject(NewClient);

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

procedure TServerFrmMain.ServerExecute(AThread: TIdPeerThread);
var
  ActClient, RecClient: PClient;
  CommBlock, NewCommBlock: TCommBlock;
  RecThread: TIdPeerThread;

begin
  if not AThread.Terminated and AThread.Connection.Connected then
  begin
    AThread.Connection.ReadBuffer (CommBlock, SizeOf (CommBlock));
    ActClient := PClient(AThread.Data);
    ActClient.LastAction := Now;  
     .
     .
     .
  end;
end;

procedure TServerFrmMain.ServerDisconnect(AThread: TIdPeerThread);
var
  ActClient: PClient;

begin
  ActClient := PClient(AThread.Data);
  Protocol.Lines.Add (TimeToStr(Time)+' Disconnect from "'+ActClient^.DNS+'"');
  try
    Clients.LockList.Remove(ActClient);
  finally
    Clients.UnlockList;
  end;
  FreeMem(ActClient);
  AThread.Data := nil;
end;

procedure TServerFrmMain.FormCreate(Sender: TObject);
begin
  Clients := TThreadList.Create;
end;

procedure TServerFrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Server.Active := False;
  Clients.Free;
end;

Z góry dziękuje za pomoc

0

Mam podobny problem z serwerem FTP INDY. Wydaje mi się, że jedynym sposobem bezpiecznego odłączenia serwera jest wcześniejsze odłączenie wszystkich połączonych z nim klientów. Serwer może zrobić to na 2 sposoby: delikatnie - wysyłając polecenie do klienta aby sam się odłączył lub stanowczo - serwer sam zamyka aktualne gniazdo z klientem.

0

Witam

Od niedawna również rozpocząłem zabawę w tworzeniu serwera za pomocą INDY i szybko natrafiłem na ten błąd.: raised exception class EIdClosedSocket with Message "Disconnected"
Niestety nie potrafię go rozwiązać jedynie umiem go wyeliminować.

Błąd ten wyskakuje w momencie gdy mamy oprogramowaną funkcję onDisconnect dla Servera.

            void __fastcall TForm1::IdTCPServer1Disconnect(TIdContext *AContext)
            {
              try{     Memo1->Lines->Add("Rozłączono: "+AContext->Binding()->PeerIP); }
              catch(...){}
            }

Nawet umieszczenie try catch mi nie dało rezultatu...
... i wyrzucało wyjątek z zawieszeniem programu.

Zawieszanie programu udało mi się wyeliminować poprzez podmienienie funkcji IdTCPServer1Disconnect na funkcję bez kodu podczas rozłączania serwera;

            IdTCPServer1->OnDisconnect=myIdTCPServer1Disconnect;
    	IdTCPServer1->Active=false;
            IdTCPServer1->OnDisconnect=IdTCPServer1Disconnect;

Po rozłączeniu przywrócenie starej funkcji

Satysfakcją jest to że program Servera się nie zawiesza jednak faktycznie problemu błędów rozłączania nie rozwiązuje.

Jeśli ktoś by był jeszcze w stanie wyjaśnić jak rozwiązać ten problem - byłoby fajnie.

Pozdrawiam

1 użytkowników online, w tym zalogowanych: 0, gości: 1