Ciao a tutti ho un problema, o meglio vorrei un chiarimento su server con un thread che gestisce le connessioni.
La mia classe server è fatta così:
server.h
codice:
class Server
{
public:
/**
*\brief Costruttore della classe
*/
Server ();
/**
*\brief Distruttore della classe
*/
virtual ~Server();
/**
*\brief Metodo che fa partire il server
*/
void Start();
/**
*\brief Metodo che ferma il server
*/
void Stop();
/**
*\brief Metodo che imposta il segnale di spegnimento del server e attende il completamento delle operazioni
*/
void WaitForCompletation();
private:
/**
*\brief Metodo che implementa la routine del server e lo pone in ascolto sulla porta specificata nel file di configurazione
*/
void Run ();
/**
*\brief Metodo che viene richiamato nel caso di una nuova connessione sul server principale e gestisce le richieste.
*/
void serviceRoutine(Socket * sock);
private:
Centrale * centrale;
// unsigned char pacchetto[512];
// unsigned char recvBuffer[512];
Database * db_epro;
Parametri * param;
Logger * log;
Socket serversock;
thread mainthread;
thread thread_serventi[10];
int n_thread;
bool thread_stop;
};
#endif // SERVER_H
server.cpp
codice:
Server::Server()
{
#if (DEBUGSERVER >=2)
cout<<"Chiamato costruttore della classe server\n";
#endif
Server::param = new Parametri(FILEPARAM);
#if (DEBUGSERVERs >=2)
cout<<"Chiamato new Parametri\n";
#endif
Server::db_epro = new Database(param->getParametro(DATABASE), //Nome db
param->getParametro(IP_DB), //IP del db
param->getParametro(PORT_DB), //Porta del db
param->getParametro(USER_DB), //Nome utente
param->getParametro(PASSWD_DB)); //Password di accesso
Server::log = new Logger(param->getParametro(FILELOG),param->getParametro(PATHLOG));
n_thread = 0;
}
Server::~Server()
{
cout<<"Distruttore del server\n";
delete param;
delete db_epro;
delete log;
}
void Server::WaitForCompletation()
{
Server::Stop();
for (int i = 0; i<n_thread; i++)
{
thread_serventi[i].join();
}
mainthread.join();
}
void Server::Stop()
{
thread_stop = true;
}
void Server::Start()
{
for(int i = 0 ; i< n_thread; i++)
{
thread_serventi[i].join();
}
mainthread = std::move(std::thread(&Server::Run,this));
thread_stop = false;
}
void Server::Run()
{
Socket serversock;
Socket new_sock;
stringstream Stream;
if(!serversock.create())
{
throw SocketException ("Could not create client socket.");
return;
}
cout<< "Creazione avvenuta con successo\n";
if(!serversock.bind(atol(param->getParametro(PORTASCOLTO).c_str())))
{
throw SocketException ( "Could not bind to port." );
return;
}
cout<< "Binding OK!!!\n";
if ( ! serversock.listen() )
{
throw SocketException ( "Could not listen to socket." );
}
cout<< "Listening OK!!!\n";
serversock.set_non_blocking(true);
while(!thread_stop)
{
serversock.accept(new_sock);
if (new_sock.is_valid())
{
cout<<"Ricevuta connessione\n";
thread_serventi[n_thread] = move(thread(&Server::serviceRoutine,this,&new_sock));
n_thread++;
}
}
cout<<"Fermato thread principale del server\n";
return;
}
void Server::serviceRoutine(Socket * sock)
{
unsigned char recvBuff[512];
unsigned char pacchettoinv[512];
Centrale * centrale = NULL;
int start = 0;
int len = 0;
short crc = 0XFFFF;
long codice = 0;
stringstream Stream;
int nelem;
int n;
string query;
PGresult * res;
sock->set_non_blocking(false);
while(!thread_stop)
{
memset(recvBuff,'\0',512);
start = 0;
///Ricezione del pacchetto
n = sock->recv(recvBuff);
cout<<"Ricevuto pacchetto\n";
///Trovo il byte iniziale in caso il buffer sia sporco
while((recvBuff[start]!= 0x0A) && (start <n))
{
start++;
}
if (n<=0)
{
break;;
}
else
{
printf("Il valore 0x0A si trova in posizione %d\n", start);
len = recvBuff[start+1];
crc = (recvBuff[start+len+3]&0xFF)+((recvBuff[start+len+4]&0xFF)<<8);
///Controllo che il pacchetto sia corretto.
if ((crc&0xFFFF) == Crc_16(&recvBuff[start],len+3))
{
///Individuo il tipo di pacchetto e mi comporto di conseguenza
switch(recvBuff[start+2])
{
case 0x01:///Pacchetto iniziale
{
cout<<"Identificato pacchetto iniziale\n";
memset(pacchettoinv,'\0',512);
codice = (((recvBuff[start+3]>>4)&0x0F)*100000)+
((recvBuff[start+3]&0x0F)*10000) +
(((recvBuff[start+4]>>4)&0x0F)*1000) +
((recvBuff[start+4]&0x0F)*100) +
(((recvBuff[start+5]>>4)&0x0F)*10) +
((recvBuff[start+5]&0x0F)*1) ;
Stream<<codice;
query = "SELECT ce_modalita_telegestione FROM centrali WHERE ce_id = '";
query.append(Stream.str());
query.append("';");
res = db_epro->eseguiQuery(query,1);
if ((strcmp(PQgetvalue(res,0,0),"TECNOOUT")==0)||(strcmp(PQgetvalue(res,0,0),"TECNO OUT")==0))
{
centrale = new xxx(codice);
//centrale->Start();
}///Qui si introdurranno altre centrali
else
{
cout<<"Centrale non valida\n";
n_thread--;
return;
}
pacchettoinv[0] = 0x0A;
pacchettoinv[1] = 0x00;
pacchettoinv[2] = 0x09;
crc = Crc_16(pacchettoinv,3);
pacchettoinv[3] = crc & 0xFF;
pacchettoinv[4] = (crc >> 8) & 0xFF;
sock->send(pacchettoinv,5);
break;
}
case 0x03: ///Richiesta stato della centrale
{
cout<<"Identificato pacchetto richiesta stato centrale\n";
memset(pacchettoinv,'\0',512);
pacchettoinv[0] = 0x0A;
pacchettoinv[1] = 0x01;
pacchettoinv[2] = 0x06;
pacchettoinv[3] = centrale->getStatoCentrale();
crc= Crc_16(pacchettoinv,4);
pacchettoinv[4] = crc & 0xFF;
pacchettoinv[5] = (crc >> 8) & 0xFF;
sock->send(pacchettoinv,6);
break;
}
case 0x04: ///Richiesta stato della zona
{
cout<<"Identificato pacchetto richiesta stato zona\n";
memset(pacchettoinv,'\0',512);
nelem=(((recvBuff[start+3]>>4)&0x0F)*1000) +
((recvBuff[start+3]&0x0F)*100) +
(((recvBuff[start+4]>>4)&0x0F)*10) +
((recvBuff[start+4]&0x0F)*1);
pacchettoinv[0] = 0x0A;
pacchettoinv[1] = 0x01;
pacchettoinv[2] = 0x07;
pacchettoinv[3] = centrale->getStatoZone(nelem);
crc= Crc_16(pacchettoinv,4);
pacchettoinv[4] = crc & 0xFF;
pacchettoinv[5] = (crc >> 8) & 0xFF;
sock->send(pacchettoinv,6);
break;
}
case 0x05: ///Richiesta stato della partizione
{
cout<<"Identificato pacchetto richiesta stato partizione\n";
memset(pacchettoinv,'\0',512);
nelem=(((recvBuff[start+3]>>4)&0x0F)*10) +
((recvBuff[start+3]&0x0F)*1) ;
pacchettoinv[0] = 0x0A;
pacchettoinv[1] = 0x01;
pacchettoinv[2] = 0x08;
pacchettoinv[3] = centrale->getStatoPartizioni(nelem);
crc= Crc_16(pacchettoinv,4);
pacchettoinv[4] = crc & 0xFF;
pacchettoinv[5] = (crc >> 8) & 0xFF;
sock->send(pacchettoinv,6);
break;
}
}
}
else
{
cout<<"Errore nel CRC\n";
}
}
}
if (centrale != NULL)
{
//centrale->WaitForCompletation();
delete centrale;
cout<<"Qui ci arrivo\n";
}
sock->chiudi();
n_thread--;
return;
}
ora il mio dubbio è:
nel metodo Run è giusto creare un array di thread e attivarli mano a mano che ricevo connessioni
o sarebbe meglio avere un solo thread e farlo detached?
se si come?
Attualmente quando chiudo il programma ho un errore e credo sia dovuto al fatto di avere dei thread in sospeso.