Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it L'avatar di Jey
    Registrato dal
    Jan 2013
    Messaggi
    41

    [Delphi] Problema http server

    Buongiorno a tutti,

    sto sviluppando un applicativo delphi che faccia da server http utilizzando il componente TIdHTTPServer.
    In parallelo sto sviluppando anche un'interfaccia web che richiede i dati al mio server tramite chiamate ajax.

    Per esser certi che il server sia attivo, lato client effettuo una chiamata ogni secondo ( watchdog ) che, in caso di esito negativo, evita di effettuare le altre chiamate fino a che non ritorna attivo il server.

    Il sistema funziona abbastanza bene, ma ho avuto alcuni problemi quali:

    1) Se spengo il server, appena lo riavvio è come se "scodasse" tutte le richieste ( watchdog ) fatte dai miei client e mi ritrovo quindi l'applicativo che accumula thread su thread;

    2) Dopo un po' di ore ( dalle 7 alle 9 ore circa ), l'applicativo crasha ( anche se ho try...except ovunque ) e mi esce il messaggio di windows "Application.exe has stopped working ecc".

    Sbaglio qualcosa io nelle impostazioni del server/client o è il componente che uso che non è ottimale?

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    A mio avviso, per approfondire la questione si dovrebbe analizzare quali sono gli strumenti che usi lato client per interrogare il tuo server, quali sono grossomodo le operazioni che svolge e come viene gestita in generale la comunicazione tra le due parti.

    Non avendo specificato nessuno di questi dettagli, diventa difficile risalire alle cause dei problemi che hai descritto; ad esempio, è praticamente impossibile dirti quale sia l'origine del crash del tuo server senza sapere cosa fa e come è stato realizzato, in pratica senza un minimo esempio di codice che ne mostri in parte l'architettura.

    Prova magari ad aggiungere qualche dettaglio in più.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Utente di HTML.it L'avatar di Jey
    Registrato dal
    Jan 2013
    Messaggi
    41
    Ok ecco un po' di codice allora:

    codice:
    procedure TCommonHttpServer.lpExecute(loRequestInfo: TIdHTTPRequestInfo; loResponseInfo: TIdHTTPResponseInfo);
    var
       loObj             :  TCommonAjaxMethod;
       loInputJson       :  TJSONObject;
       loOutputJson      :  TJSONObject;
       loStringStream    :  TStringStream;
       loCompressor      :  TIdCompressorZLib;
       lsErrorString     :  string;
    begin
       // AGU Init variables
       loInputJson       := nil;
       loStringStream    := nil;
       loCompressor      := nil;
       loObj             := nil;
       try
          if (poMethodList.Count > 0) then
          begin
             if poMethodList.TryGetValue(loRequestInfo.URI,loObj) then
             begin
                with loResponseInfo do
                begin
                   CustomHeaders.AddValue('Access-Control-Allow-Origin', '*');
                   if (loRequestInfo.CommandType = hcOPTION) then
                   begin
                      CustomHeaders.AddValue('Access-Control-Allow-Methods', 'GET,POST');
                      CustomHeaders.AddValue('Access-Control-Allow-Headers', 'Content-Type, Accept');
                      CustomHeaders.AddValue('Access-Control-Max-Age', '1728000');
                   end;
                   ContentEncoding      := 'utf-8';
                   ContentType          := 'application/json; charset=utf-8';
                   loInputJson          := TJSONObject(TJSONObject.ParseJSONValue(loRequestInfo.Params.Text));
                   loOutputJson         := loObj(loInputJson);
                   loStringStream       := TStringStream.Create(loOutputJson.ToString);
                   loCompressor         := TIdCompressorZLib.Create(nil);
                   ContentStream        := TMemoryStream.Create;
                   loCompressor.CompressStream(loStringStream, ContentStream, 9, GZIP_WINBITS, 9, 0);
                   ContentEncoding      := 'gzip';
                   ContentLength        := ContentStream.Size;
                end;
             end;
          end;
       except on E : Exception do
       end;
       if Assigned(loInputJson)    then FreeAndNil(loInputJson);
       if Assigned(loStringStream) then FreeAndNil(loStringStream);
       if Assigned(loCompressor)   then FreeAndNil(loCompressor);
       if Assigned(loOutputJson)   then FreeAndNil(loOutputJson);
    end;
    Questo è il metodo che viene chiamato all'evento OnCommandGet e OnCommandOther dell'oggetto TIdHTTPServer.

    Il mio oggetto poMethodList è una TDictionary contenente nome del metodo da chiamare e metodo da chiamare ( TCommonAjaxMethod ).
    Quest'ultimo è così definito:

    codice:
    TCommonAjaxMethod       =  function(loJson: TJSONObject): TJSONObject of object;
    Le chiamate lato client invece sono così:

    codice:
    ServerMgrClass.prototype.SendPostRequest     = function( lsUrl, lbAsync, lsDataType, loJson, lsMethodName, loOnSuccess, loOnError, loDefaultResult, liTimeout ){
       lsUrl                =  lsUrl == undefined ? this.Url : lsUrl;
       if( !loJson ){
          loJson            =  {};
       }
       loJson.isEnglish     =  false;
       loJson.sessionId     =  ( loJson.sessionId != undefined ) ? loJson.sessionId : this.SessionId ;
       var loResult         =  loDefaultResult;
       if( this.IsAlive ){
          with( this ){
             $.ajax({
                      type        :  "POST",
                      data        :  encodeURIComponent( JSON.stringify( loJson ) ),
                      dataType    :  lsDataType ? lsDataType : "json",
                      async       :  lbAsync,
                      timeout     :  ( liTimeout ? liTimeout : 5000 ),
                      url         :  lsUrl + lsMethodName,
                      success     :  function( data ){
                                        if( loOnSuccess ){
                                           loOnSuccess( data );
                                        }
                                        if( !lbAsync ){
                                           try{
                                              loResult    =  data;
                                           }
                                           catch( e ){
                                              loResult    =  null;
                                           }
                                        }
                                     },
                      error       :  function(e){
                                        if( loOnError ){
                                           loOnError();
                                        }     
                                     }
                    });
          }
       }
       else{
          if( loOnError ){
             loOnError();
          }
       }
       return loResult;
    }
    Mentre quest'ultimo è il timer di watchdog:

    codice:
    ...
    ...
    
    with( this ){
       this.Watchdog  =  setInterval(function(){
                                        $.ajax(  {
                                                    type        :  "POST",
                                                    data        :  JSON.stringify( {} ),
                                                    dataType    :  "json",
                                                    async       :  true,
                                                    timeout     :  2000,
                                                    processData :  false,
                                                    url         :  Url + "WatchDog",
                                                    success     :  function( data ){
                                                                      IsAlive        =  true;
                                                                      LastResponse   =  new Date( data.localTime );
                                                                      document.getElementById( "indexDivTimeBar" ).innerHTML   =  LastResponse.format( "dd/mm/yyyy HH:MM:ss" );
                                                                   },
                                                    error       :  function(){
                                                                      IsAlive        =  false;
                                                                   }
                                                 });
                                     }, 1000);
    }
    
    ...
    ...

  4. #4
    Ciao, uso da anni questo componentei n un programma attivo h24 e non ho mai avuto problemi. Assicurati di liberare bene la ram.

    Ciao ciao.

  5. #5
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    Ottimo per il codice, che direi fornisce un dettaglio già più preciso delle operazioni che vengono effettuate.

    In generale, non ho riscontrato grossi problemi con Indy, anche se va detto che in alcune versioni possono trovarsi dei fastidiosi buchi che dipendono anche dai componenti usati.

    Secondo me, inizierei a dotare l'applicazione di un log per tenere traccia di quello che accade, magari lasciandolo in esecuzione per una nottata; dal lato client, proverei a installare l'estensione Firebug su Firefox/Chrome per monitorare le richieste che vengono inviate e le corrispondenti risposte, verificando ad esempio perché queste si accumulano e sono reiterate pur scollegando il server.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  6. #6
    Utente di HTML.it L'avatar di Jey
    Registrato dal
    Jan 2013
    Messaggi
    41
    Grazie per le risposte, ho fatto un po' di log ma non ho avuto grandi successi.

    Ho notato però che le chiamate non si accodano ( visualizzo sulla form il numero di richieste che ricevo e all'avvio non vedo incrementare il numero a raffica ) e in più ho notato anche che tende ad accumulare thread quando sono in una certa pagina del mio sito ( che fa sulle 10 richieste asincrone contemporanee ) con vari client accesi ( 15 client da pc diversi ), quindi può essere che si incasini per problemi miei e non del componente

    Mi rimane da risolvere il crash... Non vorrei che accedo, da qualche parte, a qualche oggetto privato da più thread insieme e questo crei casino, anche se dovrei aver messo una critical section ovunque usi oggetti privati di una classe...

    Per quanto riguarda il liberare la ram invece non credo sia quello perchè l'occupazione mi rimane stabile anche dopo parecchie ore ( testandolo con 1 client non l'ho visto crashare neanche dopo giorni )

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.