| Autore |
Discussione  |
|
|
n/a
deleted
    
Città: Nascosta
1310 Messaggi |
Inserito il - 27/02/2006 : 22:46:03
|
Salve amici... ho una mia domanda (credo banale magari per alcuni di voi). Sto progettando un mio programma per la gestione delle socket in ambiente Linux. Una prima versione prevedeva la gestione concorrente di un client ad un server quest'ultima invece dovrebbe gestire più client ed allora è stato necessario generare un processo "figlio" dalla socket "padre" usando una funzione fork(tipica di Unix e quindi anche Linux ).
Questa funzione va a buon termine (ne ho la prova perchè riesco a simulare bene la connessione di più client al server aprendo diverse finestre e simulando appunto più connessioni) tuttavia riscontro un problema, abbastanza noioso, quando decido di chiudere "brutalmente" la shell che in quel momento ospita un programma client (è un evento che potrebbe capitare se un utente decidesse di farlo).
Ah... dimenticavo... nel mio programma ho previsto la chiusura dello stesso dando la possibilità ad un client di scrivere nella shell un comando da me pensato, il comando è end (che fantasia eh...),quando un utente scrive questo comando il programma effettivamente termina senza dare problemi.
Come detto prima invece, se termino il programma chiudendo la finestra senza digitare quindi il comando da me previsto per una chiusura della socket diciamo "normale" nella finestra che in quel momento ospita il server si verifica un loop (ho inserito un printf utile al debug ed ho capito quindi che lì succede qualcosa). Il server,in attesa di altre chiamate da altri client, si blocca... La mia domanda è questa, come si fa a gestire questo evento? Esiste cioè una funzione che gestisca questo evento?
Credo di essere stato un po lungo, ringrazio quindi tutte le persone che hanno dedicato un po del loro tempo alla lettura del mio problema...Ciauz Ciauz
P.S.> Spero di avere una risposta da qualche geniaccio di Voi...Ciauz Ciauz raga
|
Modificato da - n/a in Data 03/03/2006 14:56:01
|
|
|
Ohm
Moderatore
    

Città: Nazza lo sa...
810 Messaggi |
Inserito il - 28/02/2006 : 01:31:55
|
Ribadisco che questo non è un forum di programmazione, in rete ne esistono moltissimi e cosa ancor più semplice è cercare sui gruppi di conversazione inerenti al tema (htt ://groups.google[.com]), ovviamente la tua richiesta è appunto un off topic per cui non aspettarti chissà quali risposte. Sicuro di aver chiuso il socket (banale) ma può capitare che quel close() può esser dimenticato? Può darsi che il server gestisca in maniera errata le connessioni. Forse se posti i sorgenti avrai di sicuro un miglior aiuto. Cmq htt ://[www].valtellinux.it/prj/rete/ giusto per dare un'occhiata.
Ciao |
 |
|
|
fremyd
Advanced Member
    

Città: Lecce _Pisa
958 Messaggi |
Inserito il - 28/02/2006 : 15:06:31
|
ieri sera nn ho avuto tempo x risp.. cmq volevo solo dirti ke dovresti inserire + dettagli: suppongo ke il tuo programma sia in C X poter capire dov e' l' errore vedere il codice mi penso mi possa essere d aiuto.. (se e' lungo magari fai l' upload da qualke altra parta e posta solo il link..)
X il resto nn credo ke qsto post (messo tra gli OT) possa recare disturbo (magari nn otterai tantissime risposte ma tentar nn nuoce..) Certo ke da un utente ke frequenta abitualmente qsto forum mi aspettavo almeno ke inserisse un Oggetto + kiaro.. (credo ke avrebbe reso + visibile il post stesso..)
..aspetto cmq i dettagli del tuo problema.. ciauz! |
 |
|
|
n/a
deleted
    
Città: Nascosta
1310 Messaggi |
Inserito il - 28/02/2006 : 17:31:44
|
Ok... scriverò di seguito il pezzo di codice che ritengo essere incriminato... Quello che segue è un pezzo di codice che è inserito nel mio file MyServer.c
... ... ... ... ... ... while( uguale(Buffer,"end\n")<0 ) { /* Il client ha inviato il solo comando INVIO */ if( uguale(Buffer,"\n")>0 ) { printf("[CLIENT %s - AVVISO sui comandi]\n", inet_ntoa(MyClientAddress.sin_addr)); strcpy(Buffer,"Digitare un comando, per la lista dei comandi digitare help!!!"); send(DescrittoreSocketTemporaneo, Buffer, BufferSize, 0); }
/* Il client comunica la volantà di ricevere una lista degli IP */ if( uguale(Buffer,"lst\n")>0 ) { printf("[CLIENT %s - Richiesta della lista IP]\n", inet_ntoa(MyClientAddress.sin_addr)); PuntatoreFile = fopen("Tabella.txt","r"); i=0; do { fscanf(PuntatoreFile,"%c",&Buffer[i]); i=i+1; /* printf("Buffer[i]= %c\n",Buffer[i]); Un printf utile al debug */ } while( Buffer[i]!=EOF ); fclose(PuntatoreFile); send(DescrittoreSocketTemporaneo, Buffer, BufferSize, 0); printf("[MySERVER - LISTA IP inviata al client %s]\n", inet_ntoa(MyClientAddress.sin_addr)); }
/* Il client desidera avere un update sui messaggi presenti nel file */ if( uguale(Buffer,"update\n")>0 ) { printf("[CLIENT %s - Richiesta aggiornamento dei messaggi]\n", inet_ntoa(MyClientAddress.sin_addr)); PulisciBuffer(Buffer,BufferSize); PuntatoreFile = fopen("Messaggi.txt","r"); i=0; do { fscanf(PuntatoreFile,"%c",&Buffer[i]); i=i+1; } while( Buffer[i]!=EOF ); fclose(PuntatoreFile); send(DescrittoreSocketTemporaneo, Buffer, BufferSize, 0); printf("[MySERVER - ATTESA]\n"); }
/* Il client vuole comporre un messaggio da inserire nel file */ if( uguale(Buffer,"msg\n")>0 ) { printf("[CLIENT %s - Richiesta di composizione di un messaggio]\n", inet_ntoa(MyClientAddress.sin_addr)); PuntatoreFile = fopen("Messaggi.txt","a"); fprintf(PuntatoreFile,"%s >> ",inet_ntoa(MyClientAddress.sin_addr)); strcpy(Buffer,"Messaggio da scrivere (max 1024 caratteri)"); send(DescrittoreSocketTemporaneo, Buffer, BufferSize, 0); printf("[MySERVER - ATTESA]\n"); recv(DescrittoreSocketTemporaneo, Buffer, BufferSize, 0); printf("[CLIENT %s - Aggiunta di un messaggio in coda]\n", inet_ntoa(MyClientAddress.sin_addr)); fprintf(PuntatoreFile,"%s\n",Buffer); fclose(PuntatoreFile); strcpy(Buffer,"Messaggio inserito in coda"); send(DescrittoreSocketTemporaneo, Buffer, BufferSize, 0); printf("[MySERVER - ATTESA]\n"); }
/* Le seguenti righe mostrano al client un elenco dei possibili c omandi */ if( uguale(Buffer,"help\n")>0 ) { printf("[Client %s - HELP]\n",inet_ntoa(MyClientAddress.sin_addr)); strcpy(Buffer,"Lista dei comandi di MyServer\n1. lst Permette di ricevere una lista degli indirizzi IP che si collegano a MySERVER;\n2. msg Permette di aggiungere un messaggio in coda;\n3. update Permette di ricevere i messaggi aggiunti da altri utenti;\n4. end Permette di scollegare il client;"); send(DescrittoreSocketTemporaneo, Buffer, BufferSize, 0); } printf("[MySERVER - ATTESA]\n"); recv(DescrittoreSocketTemporaneo, Buffer, BufferSize, 0); }
/* Sono uscito dal ciclo quindi il client ha mandato il comando end */ printf("[CLIENT %s - Richiesta di chiusura della sessione]\n",inet_ntoa(MyClientAddress.sin_addr));
/* Nel file dedicato ai messaggi indico che un client si è scollegato */ PuntatoreFile = fopen("Messaggi.txt","a"); fprintf(PuntatoreFile,"%s >>> sconnesso...\n", inet_ntoa(MyClientAddress.sin_addr)); fclose(PuntatoreFile); ... ... ... ... ... ... |
Modificato da - ste in data 28/02/2006 19:15:31 |
 |
|
|
n/a
deleted
    
Città: Nascosta
1310 Messaggi |
Inserito il - 28/02/2006 : 22:54:36
|
| Nazzarenoooooo......Sai come aiutarmi?!?? Magari tu conosci anche il C in maniera approffondita più di me e riesci a risolvermi il problema in quattro e quattr'otto.....Ciauz Ciauz e grazie in anticipo per la disponbilità.... |
 |
|
|
Gus
New Member


Città: Napoli
38 Messaggi |
Inserito il - 01/03/2006 : 01:30:33
|
ciao,
secondo me basta trappare il segnale di kill che il programma client riceve quando chiudi la shell. L'idea è: quando arriva il segnale di kill il client lo trappa, lo blocca, manda l'end tramite socket e poi si chiude effettivamente.
Ho fatto qualcosa del genere al lavoro, mi pare tu debba usare signal.h o qualcosa del genere.. Se non hai ancora risolto domani cerco di reperire altre informazioni (è parecchio brutto non ricordarsi più come si programma :( )
fammi sapere anche tramite messaggio privato\msn se è un problema postare di qua.. |
 |
|
|
ori
Moderatore
    

Città: Verona
2043 Messaggi |
Inserito il - 01/03/2006 : 09:20:23
|
Secondo me l'idea di Gus e` corretta. Nel file del client devi aggiungere qualcosa del genere:
void sighupresponder(int sig) { printf("SIGHUP received. Exiting\n"); exit(0); }
int main() { signal(SIGHUP,sighupresponder); printf("Waiting...\n"); sleep (10); printf("Sleep ended\n"); return (0); }
Ovviamente questo e` un test, comunque l'idea e` quella di intercettare il SIGHUP inviato dalla bash (come indicato nella manpage di bash) ai children e nel signal handler che tu definisci fai tutte le operazioni necessarie per chiudere la comunicazione con il server prima di terminare. Ovviamente la signal nel main e` una tra le prime operazioni (se non la prima) da fare. |
Modificato da - ori in data 01/03/2006 09:22:10 |
 |
|
|
ste
Moderatore
    

855 Messaggi |
Inserito il - 01/03/2006 : 13:45:58
|
| Non ho modificato il tuo sorgente. ho solo eliminato il quote che avevi messo. |
 |
|
|
n/a
deleted
    
Città: Nascosta
1310 Messaggi |
Inserito il - 01/03/2006 : 15:25:41
|
Grazie lo stesso raga ma purtroppo non ho cavato fuori un ragno dal buco come mi avete detto voi.
Tuttavia dopo 2 notti insoni a provare e riprovare ho notato facendo altre prove una cosa, stupida,un mio errore(ASD :D)orrore...
In pratica accade questo: all'interno del ciclo si svolge l'iterazione della socket del Server con quella del Client... la chiusura improvvisa del programma client blocca o meglio manda in loop la socket del Server che mi continuava a stampare a video lo stesso messaggio... Questo accadeva prima, adesso ho levato il printf che mi stampava quel messaggio; facendo questo non mi accorgo più che sul programma Server, in un punto, una socket ha terminato in maniera strana (il client ha chiuso la finestra). Quindi ho visto che comunque le altre chiamate (se effettuate da un altra finestra) andavano a buon fine... il prossimo passo è stato quello di segnare in un vettore il numero PID della socket temporanea che si collega al server... il PID mi permette di identificare quel processo e di chiuderlo con il comando kill seguito dal pid... A questo punto ho usato uno stratagemma e cioè il messaggio ENOTCONN che ritrovo nella variabile errno in caso di errori (ho dovuto aggiungere la libreria errno.h nelle include in testa-heading) quindi con un if posso vedere se la connessione con una socket temporanea è ancora valida ed in caso negativo (perchè errno contiene il codice di ENOTCONN) con il pid posso chiuderla io nel programma Server... Ciao. Grazie lo stesso per la disponbilità.....Ciauz Ciauz |
Modificato da - n/a in data 01/03/2006 15:29:32 |
 |
|
|
ori
Moderatore
    

Città: Verona
2043 Messaggi |
Inserito il - 01/03/2006 : 16:40:44
|
Nel tuo procedimento mi sembra che ci siano alcuni problemi: 1) il server va in loop ma tu togli il feedback. Comunque consuma risorse. 2) il kill puoi lanciarlo solo a processi con lo stesso uid o da root. 3) il server fa un polling per vedere cosa c'e` di valido e cosa no, con un consumo di risorse.
Questi problemi come pensi di risolverli (in particolare il secondo, visto che in genere i client girano sotto vari utenti e il server sarebbe meglio se girasse con permessi non di root)? |
 |
|
|
n/a
deleted
    
Città: Nascosta
1310 Messaggi |
Inserito il - 02/03/2006 : 15:35:19
|
Citazione: Messaggio inserito da ori
Nel tuo procedimento mi sembra che ci siano alcuni problemi: 1) il server va in loop ma tu togli il feedback. Comunque consuma risorse. 2) il kill puoi lanciarlo solo a processi con lo stesso uid o da root. 3) il server fa un polling per vedere cosa c'e` di valido e cosa no, con un consumo di risorse.
Questi problemi come pensi di risolverli (in particolare il secondo, visto che in genere i client girano sotto vari utenti e il server sarebbe meglio se girasse con permessi non di root)?
Scusate il ritardo ma sono stato molto impegnato ultimamente...[.com]unque ritornando al nostro discorso caro Ori devo dire che mi fa piacere leggere queste domande, perchè dimostrano un senso di perspicacia e di interessamento da parte di utenti come te ..
Allora per quanto riguarda il primo punto è vero che nella finestra del server non ho più un feedback; cioè non ho più a video una scritta che mi dice cosa il server sta facendo e per questo infatti ho preferito fare in un altro modo, perchè dovendo mostrare il programma in fase di esecuzione e durante una sua presentazione(infatti questa release è beta e dimostrativa) temevo che questo comportamento avrebbe potuto manifestarsi in un particolare evento (tipo la chiusura della finestra client); ovviamento ho poi pensato ad una soluzione (cioè la notifica con un semplice messaggio delle operazioni salienti a video, tipo un'apertura di una connessione o la sua chiusura). Per il secondo punto invece il kill lo lancio da root(questo perchè il programma sarebbe dedito ad una rete locale nella quale con un protocollo alternativo andremmo gestire le risorse SMB e NFS) identificando la socket che si è interrotta con il suo specifico pid. Lo so che anche questo potrebbe essere una forte limitazione ma non mi sono messo a cercare soluzioni più eleganti per mancanza di tempo e per dare la prorità ad altre ricerche e esperimenti che mi sono più utili sulle socket e le gestioni delle comunicazioni basilari di Rete di questo programma. In poche parole visto che l'uso che ne vado a fare del programma (questa è una prova stilistica della programmazione client/server sulle socket Linux per poter così cominciare a testare i protocolli comuni per andare a crearne un nostro nuovo in maniera mirata e diretta ). Per quanto riguarda il polling concordo con te sul fatto che le risorse usate e lo spreco della memoria, quando una socket "figlia" rimane bloccata, possano essere ingenti. Tuttavia la risposta alla tua domanda sta ancora una volta nell'utilizzo che avevo in mente per il programma più una piccola modifica che risiede nella gestione delle SR; perchè infatti ho voluto verificare e fare alcuni calcoli, e se guardi una socket figlia che rimane bloccata richiede costantemente 4.064Kb di memoria, e avendo previsto nel programma server al massimo 150 connesioni ed ipotizzando che, nel caso peggiore, tutte vengano bloccate in maniera inopportuna si avrebbe al massimo una richiesta di memoria pari a 609600Kb (150 x 4064) pari a 595,31Mb (609600/1024). Nel caso di questa bruttissima ipotesi l'SO va giù, ma questo era ovvio e l'ho fatto solo per calcolare il limite massimo oltre la quale non è possibile generare nemmeno una socket (in realtà potrei in errno trovare il codice 12 che equivale al messaggio ENOMEM, not enough space, tuttavia questo avviene prima poichè una quota i memoria è dedicata al SO)... Tuttavia siccome il programma server girerà su un computer con 2Gb di RAM e gli host della rete sono al massimo 37, mi è bastato per ripicca gestire un'apposita SR inserendo una function che verifica la RAM libera impostando un flag X e una function che gestisce un flag Y permettendomi di forzare la routine per bloccare il numero di socket aperte fino a quando non si sarà chiusa almeno una socket open. Così facendo eviterò di far crashare l'SO e di andare a scrivere nella memoria dedicata al sistema.
Grazie per le domande ma bene o male le idee da te sottolineate mi erano già sorte nel testing del programma quando sono riuscito a farlo funzionare e quindi ho già cercato dei rimedi per correre ai ripari.....tuttavia se hai qualche idea migliore è bene accetta!!! Aspetto ansioso una tua risposta con nuove idee e <"critiche"> in merito....Ciauz Ciauz |
Modificato da - n/a in data 03/03/2006 12:33:54 |
 |
|
|
ste
Moderatore
    

855 Messaggi |
Inserito il - 03/03/2006 : 15:12:14
|
E' incredibile come alcuni di voi abbiano continuamente e ripetutamente secondi fini in tutto. Questa discussione è stata creata dal Signor EcNx82.CYpTO al solo scopo di aumentare il proprio prestigio all'interno della Community, altrimenti non si spiegherebbero le continue modifiche ad essa in modo da far rimanere il 3d nella classifica degli ultimi post dal forum, pur non avendo nessun articolo nuovo. E' ora di finirla. Questi giochetti sono vecchi e antipatici, e vanno avanti oramai da troppo tempo. Come proveddimento minimo ed immediato, ti chiudo la discussione. Seguiranno news che ti recapiterò personalmente.
|
 |
|
| |
Discussione  |
|
|
|