Salve,
sto implementando un server che rimane in attesa di connessioni da parte di client, ricevute le quali, lancia un nuovo thread a cui passa la connessione ottenuta.
Per gestire al meglio le operazioni di terminazione di tale server, ho utilizzato una select che gestisce il timeout per la accept sul socket d'ascolto.
Però da quando ho aggiunto la select il mio server non funziona più a dovere: i thread(server dedicati) terminano improvvisamente la loro connessione!
Posto il codice del server principale:
/* main */
codice:
int main(int argc, char* argv []){
/* AMBIENTE WINDOWS */
HANDLE ListaServer[MAX_SERV];
HANDLE Console;
DWORD ConsoleId;
DWORD ServID[MAX_SERV];
SOCKADDR_IN Client_addr;
SOCKET listenSocket;
SOCKET connessione;
int id_serv,sin_size,i,n;
LONG cnt;
LONG volatile flag;
LONG volatile client[MAX_SERV];
serv_arg* param;
fd_set rset;
struct timeval tv;
u_long iMode;
/*inizializzazione libreria Socket*/
WORD wVersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
int wsastartup = WSAStartup(wVersionRequested, &wsaData);
if (wsastartup != NO_ERROR) printf("Errore WSAStartup()\n");
id_serv=0;
for(i=0;i<MAX_SERV;i++) client[i]=0;
/* Creazione Thread che rimane in attesa del segnale di terminazione dell'applicazione */
Console=(HANDLE)_beginthreadex(NULL,0,(LPTHREAD_START_ROUTINE)Listener,&flag,0,&ConsoleId);
/*Inizializzazione connessione server*/
listenSocket=ConnessioneServer("127.0.0.1",N_PORT,listenSocket);
if(listenSocket==INVALID_SOCKET){
printf("Errore ConnessioneServer\n");
return -1;
}
iMode=1;
ioctlsocket(listenSocket, FIONBIO, &iMode);
flag=1;
printf("Mainserver in attesa di client..\n");
while(flag){
FD_ZERO(&rset);
FD_SET(listenSocket, &rset);
tv.tv_sec = 10;
tv.tv_usec = 0;
if( (n = select(listenSocket + 1, &rset, NULL, NULL, &tv)) < 0 ){
printf("Errore Select:%d\n",WSAGetLastError());
return -1;
}
if(n>0){
connessione = accept(listenSocket, (struct sockaddr*)&Client_addr, &sin_size);
if(connessione<=0) printf("Errore Accept:%d\n",WSAGetLastError());
printf("Accettata Connessione con Client: %s su socket %d\n", inet_ntoa(Client_addr.sin_addr),connessione);
param=malloc(sizeof(serv_arg));
for(i=0;i<MAX_SERV;i++) {
if(client[i]==0){
InterlockedIncrement(&(client[i]));
break;
}
}
(*param).nserv=&(client[i]);
(*param).idServ=i;
(*param).conn=connessione;
(*param).clientAddr.sin_family = AF_INET;
(*param).clientAddr.sin_addr.s_addr=Client_addr.sin_addr.s_addr;
(*param).clientAddr.sin_port=Client_addr.sin_port;
ListaServer[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)server,param,0,&ServID[i]);
}
}
/*rimane in attesa che tutti i server dedicati terminino */
while(1){
cnt=0;
for(i=0;i<MAX_SERV;i++) cnt+=client[i];
if(cnt==0) break;
else Sleep(10000);
}
/*quindi termina */
shutdown(listenSocket,2);
close(listenSocket);
WSACleanup();
return 0;
}
ho aggiunto la temporizzazione mediante select poichè il server avvia all'inizio un thread in ascolto sulla console, il quale pone flag=0 quando viene scritto quit sulla console.
Senza tale temporizzazione il server sarebbe rimasto comunque in attesa di un ultima richiesta di connessione sulla accept. Mentre in questo modo sen entro il tempo stabilito non giungono nuove richieste di connessione il server può uscire tranquillamente dal ciclo while e condurre le operazioni di terminazione.
Perchè questo influisce sul comportamento della connessione mantenuta dal server dedicato(il thread che fa riferimento alla funzione server)?