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:
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
//---------------------------------------------------------------------------
// *******************************************************
//--------------------------------------------------------------------------- |
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:
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();
} |