PDA

Visualizza la versione completa : Gestione segnali per Client-Server Windows


Diego__87
25-08-2012, 16:26
Salve, sto implementando un programma Client Server ed ho la necessit di gestire dei segnali asincroni come :


signal(SIGINT, chiusuraClient);
signal(SIGQUIT, chiusuraClient);
signal(SIGILL, chiusuraClient);
signal(SIGSEGV, chiusuraClient);
signal(SIGTERM, chiusuraClient);

signal(SIGPIPE, SIG_IGN);

solo che non riesco a trovare il codice equivalente per gestire tali segnali in Windows;
inoltre avrei la necessita di gestre anche un timer che mi faccia chiudere la connessione del Client se questo rimane inattivo per molto tempo, in modo da liberare la connessione;
so che in UNIX si usa SIGALARM, mentre non s come poter gestire la cosa in Windows.

Qualcuno sarebbe cos gentile da darmi una mano?

Grazie.

denis76
25-08-2012, 20:47
In Win si usa PostMessage e SendMessagge

http://msdn.microsoft.com/en-us/library/windows/desktop/ms644944%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644950%28v=vs.85%29.aspx

Ciao ciao.

Diego__87
26-08-2012, 12:09
Grazie infinite per avermi risposto,
per perdonami ma non rieso a capire come queste due funzioni possano fare al caso mio, leggendo le api mi sembra di aver capito che necessitano inoltre di un handle di una finestra grafica, mentre il mio programma di tipo console...

potresti spiegarmi come dovrei usarle per cortesia...?

denis76
26-08-2012, 15:26
L'handle il riferimento della finestra principale del programma al quale vuoi mandare un messaggio come ad esempio l'ordine di chiusura.
Scrivi client - server, il programma console (credo che sia il server) in che modo dialoga il client e com' fatto il client?

Diego__87
26-08-2012, 17:51
Allora il mio Client questo:


int loginOK;
SOCKET sock;
struct sockaddr_in sock_addr;
WSADATA data;
WORD p;
int err=0;
int porta;
int opzione;
p=MAKEWORD(2,0);
WSAStartup(p,&data);
sock=socket(PF_INET,SOCK_STREAM,0);
sock_addr.sin_family=PF_INET;
porta=1001;
sock_addr.sin_port=htons(porta);
sock_addr.sin_addr.S_un.S_un_b.s_b1=127; sock_addr.sin_addr.S_un.S_un_b.s_b2=0; sock_addr.sin_addr.S_un.S_un_b.s_b3=0; sock_addr.sin_addr.S_un.S_un_b.s_b4=1;
err=connect(sock,(struct sockaddr*)&sock_addr,sizeof(struct sockaddr));
if (err==0){
printf("Inizializzazione completata con successo\n");
/* Effettuo il login */
loginOK = login(sock);
if(loginOK == 1){
int opzione; while(1){
/* Seleziono l'opzione dal men principale */
opzione = menu();
/* Chiamo la funzione specifica per l'opzione selezionata
*/
/* Opzione "Trova record" */ if(opzione==1){
if(trovaRecord(sock) == 1){
/* Informo il server che voglio continuare con una richiesta */
while(send(sock, "OK", RISPOSTA,0) <= 0){ if(errno != EINTR){
if(errno == ECONNRESET || errno == EPIPE){
printf("\n\nCONNESSIONE INTERROTTA, il server si disconnesso in maniera scorretta!");fflush(stdout); chiusuraClient(); } else{
printf("Lettura fallita\n");fflush(stdout); perror("Errore tipo");fflush(stdout); chiusuraClient(); }
}
printf("Errore durante la system call, ripeto\n");fflush(stdout); } } else{
printf("\nIl server non risponde, offline\n"); chiusuraClient();
}
}
/* Opzione "Aggiungi record" */ if(opzione==2){
if(aggiungiRecord(sock) == 1){ printf("entrato\n");fflush(stdout);
/* Informo il server che voglio continuare con una richiesta */
while(send(sock, "OK", RISPOSTA,0) <= 0){ if(errno != EINTR){
if(errno == ECONNRESET || errno == EPIPE){
printf("\n\nCONNESSIONE INTERROTTA, il server si disconnesso in maniera scorretta!");fflush(stdout); chiusuraClient(); } else{
printf("Lettura fallita\n");fflush(stdout); perror("Errore tipo");fflush(stdout); chiusuraClient(); } } printf("Errore durante la system call, ripeto\n");fflush(stdout); }
}
else{
printf("\nIl server non risponde, offline\n"); chiusuraClient();
}
}
if(opzione==3){
/* Informo il server che ho terminato le richieste... */ while(send(sock, "OFF", RISPOSTA,0) <= 0){
if(errno != EINTR){
if(errno == ECONNRESET || errno == EPIPE){
printf("\n\nCONNESSIONE INTERROTTA, il server si è disconnesso in maniera scorretta!");fflush(stdout); chiusuraClient(); } else{
printf("La lettura fallita\n");fflush(stdout); perror("Errore tipo");fflush(stdout); chiusuraClient(); }
}
printf("Errore durante la system call, ripeto\n");fflush(stdout);
}
/* ...e chiudo il client */ chiusuraClient();
}
}
}
/* La connessione si interrotta improvvisamente */ else{
printf("\nIl server non risponde, offline"); chiusuraClient();
}
}
if (err!=0) printf ("%d porta CHIUSA\n",porta);
closesocket(sock); // chiudo la socket
WSACleanup();
//libero le risorse utilizzate dalla libreria Winsock
return 0; }

ora ti scrivo anche la funzione LOGIN...

Diego__87
26-08-2012, 17:51
Questa la funzione login che viene richiamata e in cui c' la read bloccante :



int login(int sock){
int tentativi = 3;
char risposta[RISPOSTA];
Utente utente;
printf("\n\nAttendere che il Server sia libero...\n\n");fflush(stdout);
/* Ricevo il via libera dal server */
/* QUESTA RECV PERMETTE L'ATTESA BLOCCANTE NEL CASO IN CUI PIU' CLIENT SIANO CONNESSI AL SERVER */
while(recv(sock, risposta, sizeof(risposta),0) <= 0){ //printf("\n\nVia libera del server ricevuto");fflush(stdout);
if(errno != EINTR){
if(errno == ECONNRESET || errno == EPIPE){
printf("\n\nCONNESSIONE INTERROTTA, il server si disconnesso in maniera scorretta!");fflush(stdout);
return -1;
}
else{
printf("Lettura fallita\n");fflush(stdout);
perror("Errore tipo");fflush(stdout);
return -1;
}
}
printf("Errore durante la system call, ripeto\n");fflush(stdout);
}
printf("\n--------------EFFETTUA IL LOGIN PER ACCEDERE--------------\n");fflush(stdout);
/* Resetto il valore della struct utente */
memset(utente.nickname, 0, sizeof(utente.nickname));
memset(utente.password, 0, sizeof(utente.password));
/* Resetto il valore della stringa risposta */
memset(risposta, 0, sizeof(risposta)); while(tentativi>0){
/* Digito il nickname e la password per il login */
printf("\nInserisci nickname: ");fflush(stdout);
while(scanf("%s", utente.nickname) == -1){
if(errno != EINTR){
printf("\nErrore scanf\n");
chiusuraClient();
}
}
printf("\nInserisci password: ");fflush(stdout);
while(scanf("%s", utente.password) == -1){
if(errno != EINTR){
printf("\nErrore scanf\n");
chiusuraClient();
}
}
printf("\n\nInvio dati in corso attendere...\n");
/* Invio il nickname al server */
while(send(sock, utente.nickname, strlen(utente.nickname),0) <= 0){ if(errno != EINTR){
if(errno == ECONNRESET || errno == EPIPE){
printf("\n\nCONNESSIONE INTERROTTA, il server si disconnesso in maniera scorretta!");fflush(stdout);
return -1;
}
else{
printf("Lettura fallita\n");fflush(stdout);
perror("Errore tipo");fflush(stdout);
return -1;
}
}
printf("Errore durante la system call, ripeto\n");fflush(stdout); }
/* Invio la password al server */
while(send(sock, utente.password, strlen(utente.password),0) <= 0){ if(errno != EINTR){
if(errno == ECONNRESET || errno == EPIPE){
printf("\n\nCONNESSIONE INTERROTTA, il server si disconnesso in maniera scorretta!");fflush(stdout);
return -1;
}
else{
printf("Lettura fallita\n");fflush(stdout);
perror("Errore tipo");fflush(stdout);
return -1;
}
}
printf("Errore durante la system call, ripeto\n");fflush(stdout); }
/* Ricevo la risposta dal server */
while(recv(sock, risposta, sizeof(risposta),0) <= 0){
if(errno != EINTR){
if(errno == ECONNRESET || errno == EPIPE){
printf("\n\nCONNESSIONE INTERROTTA, il server si disconnesso in maniera scorretta!");fflush(stdout);
return -1;
}
else{
printf("Lettura fallita\n");fflush(stdout);
perror("Errore tipo");fflush(stdout);
return -1;
}
}
printf("Errore durante la system call, ripeto\n");fflush(stdout); }
/* Login effettuato con successo */
if(strcmp(risposta, "OK") == 0){
printf("\nLogin effettuato con successo\n\n");
memset(risposta, 0, sizeof(risposta));
return 1;
}
/* Login errato, nuovo tentativo*/
if(strcmp(risposta, "NO") == 0){
printf("\nNickname o password ERRATI\n");
memset(risposta, 0, sizeof(risposta));
--tentativi;
if(tentativi == 2){
printf("Hai ancora %d tentativi di LOGIN\n", tentativi); }
if(tentativi == 1){
printf("Hai ancora %d tentativo di LOGIN\n", tentativi); }
premiInvio();
}
}
/* Login definitivamente fallito dopo 3 tentativi errati */
if(tentativi == 0){
printf("\nTentativo di LOGIN fallito\n");
chiusuraClient();
}
}
io in pratica vorrei mettere un timeout che chiuda la connessione con il Client se questo non effettua il login o richiede un'operazione entro un tot di tempo, in modo da liberare il server e passare al prossimo Client in coda...

denis76
26-08-2012, 23:56
b, non ho letto tutto, dovresti cercare di essere un po' pi sintetico.
Se ho ben capito vuoi che se un client si collega in tcp senza autenticarsi entro un certo tempo venga chiusa la connessione?

Diego__87
27-08-2012, 09:43
Si proprio cos....oppure se dopo essersi autenticato questo non fa nessuna operazione e blocca il server inutilmente.

denis76
27-08-2012, 10:16
In C non l'ho mai fatto ma di solito in queste situazioni lato server instanzio un thread per ogni connessione il quale con una read con timeout e non bloccante controlla lo stato del socket di modo da chiuderlo quando non pi valido o quando non arriva nulla per un certo tempo.


Ciao ciao.

Loading