IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

arret d'un socketserver crée un exception


Sujet :

C++Builder

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2008
    Messages : 11
    Par défaut arret d'un socketserver crée un exception
    Bonjour à tous

    J'essaie de créer un serveur à partir d'un exemple trouvé (ci dessous)
    "serveur multithreaded bloquant"
    Mais lorsque j'essaie de fermer le serveur alors que la fonction WaitForData n'est pas terminée cela crée une exception "ESocketError "lecture erreur 6" , Descripteur non valide .
    Comment arrêter le serveur sans attendre la fin des fonctions WaitForData dans les divers Threads créées (je voudrais pouvoir arrêter le serveur même si des client sont connectés)


    Merci d'avance pour vos réponses

    mastok

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
     #include <vcl.h> 
    #pragma hdrstop 
    #include "ServerMain.h" 
    //--------------------------------------------------------------------------- 
    #pragma package(smart_init) 
    #pragma resource "*.dfm" 
    TForm1 *Form1; 
    //--------------------------------------------------------------------------- 
    // Wait 60 seconds for client 
    const int CLIENTWAITTIME = 60000; 
    // Size of buffer for reading/writing text across socket connection 
    const int BUFFERSIZE = 32; 
    //--------------------------------------------------------------------------- 
     
    //--------------------------------------------------------------------------- 
    __fastcall TForm1::TForm1(TComponent* Owner) 
       : TForm(Owner) 
    { 
    } 
    //--------------------------------------------------------------------------- 
     
    //--------------------------------------------------------------------------- 
    // Instead of using a client socket component that you place in your application 
    // from the Component palette, the server client thread must use the TServerClientWinSocket 
    // object that is created when the listening server socket accepts a client connection. 
    // This is available as the public ClientSocket property. In addition, you can use the 
    // protected HandleException method rather than writing your own thread-safe exception 
    // handling. 
    void __fastcall TMyServerThread::ClientExecute(void) 
    { 
       // make sure connection is active 
       while (!Terminated && ClientSocket->Connected) 
       { 
          try 
          { 
             // Now, use TWinSocketStream to read or write information 
             // over a blocking socket connection 
             TWinSocketStream *pStream = new TWinSocketStream(ClientSocket, CLIENTWAITTIME); 
     
             try 
             { 
                char buffer[BUFFERSIZE]; 
                memset( buffer, 0, sizeof(buffer) ); 
     
                // give the client 60 seconds to start writing 
                if (pStream->WaitForData(CLIENTWAITTIME)) 
                { 
                   if (pStream->Read(buffer, sizeof(buffer)) == 0) 
                      // (if can't read in 60 seconds) than close the connection 
                      ClientSocket->Close(); 
                   else 
                   { 
                      // Client to Server test text 
                      Form1->Memo1->Lines->Add(AnsiString("(Client) ") +AnsiString(buffer) ); 
     
                      // Back again to Client 
                      pStream->Write( buffer, sizeof(buffer)); 
                   } 
     
                   // ... 
                   // Process requests here. 
                   // ... 
     
                } 
                else 
                   ClientSocket->Close(); 
             } 
             __finally 
             { 
                delete pStream; 
             } 
          }
          catch (...) 
          { 
             HandleException(); 
          } 
       } 
    } 
    //--------------------------------------------------------------------------- 
     
    //--------------------------------------------------------------------------- 
    void __fastcall TForm1::ServerSocket1GetThread(TObject *Sender, 
          TServerClientWinSocket *ClientSocket, TServerClientThread *&SocketThread) 
    { 
       SocketThread = new TMyServerThread(false, ClientSocket); 
    } 
    //--------------------------------------------------------------------------- 
    // ******************************************************* 
    //--------------------------------------------------------------------------- 
    //--------------------------------------------------------------------------- 
    #ifndef ServerMainH 
    #define ServerMainH 
    //--------------------------------------------------------------------------- 
    #include <Classes.hpp> 
    #include <Controls.hpp> 
    #include <StdCtrls.hpp> 
    #include <Forms.hpp> 
    #include <ScktComp.hpp> 
    //--------------------------------------------------------------------------- 
    class TForm1 : public TForm 
    { 
       __published: // IDE-managed Components 
          TServerSocket *ServerSocket1; 
       TMemo *Memo1; 
          void __fastcall ServerSocket1GetThread(TObject *Sender, 
             TServerClientWinSocket *ClientSocket, TServerClientThread *&SocketThread); 
       private:       // User declarations 
       public:        // User declarations 
          __fastcall TForm1(TComponent* Owner); 
    }; 
    //--------------------------------------------------------------------------- 
    extern PACKAGE TForm1 *Form1; 
    //--------------------------------------------------------------------------- 
     
    //--------------------------------------------------------------------------- 
    // Threads for server connections are descendants of TServerClientThread. 
    // Thus, you may not use the New Thread object dialog. 
    // Instead, declare your thread manually as follows: 
    class PACKAGE TMyServerThread : public Scktcomp::TServerClientThread 
    { 
       public: 
          // if true, FreeOnTerminate is set to false before the thread terminates, 
          // and the thread is left in the thread cache. When KeepInCache is false, 
          // the thread is freed when execution terminates. 
          __fastcall TMyServerThread(bool CreateSuspended, TServerClientWinSocket* ASocket) 
             : Scktcomp::TServerClientThread(CreateSuspended, ASocket) 
             { CreateSuspended = false; KeepInCache=true; FreeOnTerminate=false; }; 
     
          // To implement this thread, you override the ClientExecute method instead of the Execute method. 
          void __fastcall ClientExecute(void); 
    }; 
    //--------------------------------------------------------------------------- 
    #endif 
    //--------------------------------------------------------------------------- 
    // ******************************************************* 
    //---------------------------------------------------------------------------

  2. #2
    Expert confirmé

    Avatar de pottiez
    Homme Profil pro
    Développeur C++
    Inscrit en
    Novembre 2005
    Messages
    7 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur C++
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2005
    Messages : 7 152
    Par défaut
    Tu peut éviter d'afficher l'erreur grâce à l'évènement OnClientError de ton TServerSocket, et dans cet evenement, tu met :

    Par contre, il te sera impossible d'éviter l'erreur puisque tu coupe le serveur avec des clients encore connecté.

  3. #3
    Membre expérimenté Avatar de Mattetfamilly
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    182
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 182
    Par défaut
    Par contre, il doit y avoir moyen de déconnecter les clients un par un en accédant au sockets ouverts disponibles dans la liste des sockets...

    Sinon, de la même manière que tu as du créer un protocole de communication pour les échanges des clients vers le serveur, tu peux créer un protocole de communication pour les échanges du serveur vers les clients pour les avertir que tu arrêtes le serveur et ainsi forcer les applications client à se déconnecter avant d'arrêter ton serveur...
    Cette façon de faire permet aussi de manière conviviale d'avertir les utilisateurs au leiu de les planter "méchament"...

    @+
    Mattetfamilly

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2008
    Messages : 11
    Par défaut modification du code suivant vos idées
    Merci pour vos idées

    J'ai modifié le code en suivant votre conseil.
    Maintenant en utilisant le pointeur sur thread et ->terminate() je ferme toutes les connexions clients une après les autres c'est OK.
    Mais maintenant lorsqu'un client se déconnecte "ClientSocket->Connected"
    reste continuellement à True Le thread ne se termine plus sauf intervention de l'administrateur et pStream->WaitForData(CLIENTWAITTIME) me retourne continuellement 1 alors que le client est déconnecté

    Voici le nouveau code

    si vous avez une idée ??

    Merci d'avance

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    void __fastcall TMyServerThread::ClientExecute(void)
    {
        BOOL  bClientQuery = FALSE;
        DWORD  ConnectOk = 1;
        int IRead ;
     
       // make sure connection is active
     
     while (!Terminated && ClientSocket->Connected  )
         {
          try
          {   //try1
             // Now, use TWinSocketStream to read or write information
             // over a blocking socket connection
             pStream = new TWinSocketStream(ClientSocket, CLIENTWAITTIME);
     
             try //try2
             {
                char buffer[BUFFERSIZE];
                memset( buffer, 0, sizeof(buffer) );
     
                // give the client 60 seconds to start writing
                IRead=pStream->WaitForData(CLIENTWAITTIME)  ;
                  if (IRead>0)
                    {
                      if (pStream->Read(buffer, sizeof(buffer)) != 0)
                         {
     
                           bClientQuery=CommandRead (buffer,sizeof(buffer) ) ;
     
                                  if ( bClientQuery)
                                      {   ConnectOk = ConnectB () ;
                                         ErrorStatus ("Error ConnectB " , ConnectOk);
     
                                       }
                                switch (ConnectOk)
                                   { //switch
                                       case 0:
                                            bClientOkD = TRUE;
                                          for (int i=0; i<=10;i++)
                                            {
                                             pStream->Write(szOkResult, 8);
                                            }
                                         Synchronize (UpdateMemo4);
                                          ReadStatCD();
                                            break;
                                        case 2:
     
                                           strcpy (szOkResult,"\x23\xFA\x2c""Cerr");
                                            pStream->Write(szOkResult, 8);
                                            break;
     
     
                                        case 5:
     
                                           strcpy (szOkResult,"\x23\xFA\x2c""Busy");
                                            pStream->Write (szOkResult, 8);
                                            break;
                                            default:
                                      // UpdateStatus("No Read C.\r\n");
                                            break;
     
                                      } //switch
     
     
                            }
     
                         }
     
     
     
     
             }  //try
            __finally
             {
               delete pStream;
             }
          }//try
          catch (...)
          {
             HandleException();
          }
        }   //while
     
     ClientSocket->Close();
     
    }

Discussions similaires

  1. Réponses: 4
    Dernier message: 09/05/2012, 09h47
  2. [Quartz] Arreter quartz quand mon appli lance une exception
    Par Shogun dans le forum API standards et tierces
    Réponses: 1
    Dernier message: 17/01/2008, 15h41
  3. Crée un Script Qui va M'arreter un service dans Windows ..
    Par The_Haunted dans le forum Windows XP
    Réponses: 7
    Dernier message: 02/08/2007, 16h36
  4. Réponses: 7
    Dernier message: 09/10/2006, 16h11
  5. Réponses: 4
    Dernier message: 04/08/2005, 14h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo