Visualizzazione risultati 1 fino 8 di 8

Discussione: [DEV] Soket C e processi <defunti>

  1. #1
    L'avatar di radioradianti
    radioradianti non è connesso Utente storico
    Data registrazione
    26-11-2003
    Residenza
    Roma
    Messaggi
    1,000

    Question [DEV] Soket C e processi <defunti>

    Ho sviluppato un socket server in C sotto Linux.

    Questo server permette fino a 20 connessioni client.
    Tutto funziona correttamente, i client si collegano, fanno il loro lavoro e si scollegano.

    Ho però notato una cosa, ogni volta che un client si scollega lascia un processo figlio che viene definito "defunto", finche il server non si arresta e quindi muore il padre.

    Ora la mia domanda è la seguente :
    E' possibile rimuovere i processi "defunti" ? Se si come faccio?

    Se dovessi lasciarli, considerando la percentuale di connessioni giornaliere, effettuando un semplice comano "ps -ef | grep s_server" stare circa 2 ore a vedermi scorrere di fronte righe!!!

    Grazie per l'aiuto

    Leandro

    Happy Slack! :smile:

    E' on line il numero 12 di Topolinux - Totalmente rinnovato!
    TopoLinux è anche chat! irc.azzurra.org canale #topolinux
    La semplicità di questo dono è inversamente proporzionale alla qualità della nostra amicizia

  2. #2
    Guest

    Predefinito

    Cosi' senza vedere nel dettaglio il codice mi vien da dire che in qualche modo il processo figlio rimane appeso in attesa di chiusura della connessione...
    L'unica cosa che posso dirti e' di provare a vedere con un netstat -na a vedere se le relative connessioni sono in attesa di chiusura (dovrebbe segnarti un FIN_WAIT o qualcosa di simile)? Nel caso in cui siano in quello stato dovresti essere piuttosto sicuro che non sia un problema del codice. Magari prova ad abilitare i KEEPALIVE e a settare con le relative sysctl i tempi di keepalive.
    Ad esempio puoi dare un'occhiata qui (cerca nella pagina keepalive) o qui.
    Spero di essere stato un minimo di aiuto :smile:

  3. #3
    L'avatar di radioradianti
    radioradianti non è connesso Utente storico
    Data registrazione
    26-11-2003
    Residenza
    Roma
    Messaggi
    1,000

    Predefinito

    Citazione Originalmente inviato da dndvault
    ......
    L'unica cosa che posso dirti e' di provare a vedere con un netstat -na a vedere se le relative connessioni sono in attesa di chiusura (dovrebbe segnarti un FIN_WAIT o qualcosa di simile)? Nel caso in cui siano in quello stato dovresti essere piuttosto sicuro che non sia un problema del codice.......

    Ho effettuato il controllo che mi hai detto ed effettivamente i processi defunti si trovano in TIME_WAIT.

    Da quello che mi hai scritto,mi sembra di capire che quei processi sono in attesa di terminazione, è corretto?
    Se così fosse, una volta spariti dal comando
    netstat
    dovrebbero anche sparire dal
    ps -ef | grep s_server
    ma ciò non accade.

    Ti allego quì sotto il una parte del codice incriminato :
    ........
    .....
    ........
    .......

    // Creazione del socket e
    // riempimento della struttura server
    //------------------------------------

    if (( sd = socket(AF_INET,SOCK_STREAM,0)) < 0)
    printf("Errore nella creazione del sever!\n");

    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = INADDR_ANY;

    //Assegnazione al socket di un processo tramite funzione BIND
    //-----------------------------------------------------------
    if (bind(sd,(struct sockaddr *)&server,sizeof(server)) <0 )
    printf("Errore nella chiamata di sitema BIND!\n");

    //Messa in ascolto del server
    //---------------------------
    listen(sd,MAX_CONNECTION);

    //Ciclo infinito di ascolto
    //-------------------------
    while(1) {
    [INDENT] if ((temp_sd=accept(sd,(struct sockaddr *)&client,&address_size)) < 0)
    {
    printf ("Errore durante la chiamata ACCEPT\n");
    exit(-1);
    }

    if ((pid = fork()) < 0)
    {
    perror("fork error\n");
    exit(-1);
    }

    if (pid == 0) { //ci troviamo nel figlio

    close(sd);

    //Pulizia dello schermo terminale
    //-------------------------------
    pulisci_schermo (temp_sd);

    //Visualizzazione del titolo e menu
    //---------------------------------
    stampa_messaggio (temp_sd);

    //Attesa ricezione scelta
    //-----------------------
    ricevi_dati(temp_sd,dati_ricevuti);

    printf ("Dati ricevuti : %s\n",dati_ricevuti);
    close(temp_sd);

    exit(0);
    }
    else { //Mi trovo nel padre

    close(temp_sd);
    }

    }
    exit(0);

    }
    ...........
    ........
    ............
    ......
    spero possa esserti di aiuto per il mio problema.

    Grazie in anticipo

    Leandro

    Happy Slack! :smile:

    E' on line il numero 12 di Topolinux - Totalmente rinnovato!
    TopoLinux è anche chat! irc.azzurra.org canale #topolinux
    La semplicità di questo dono è inversamente proporzionale alla qualità della nostra amicizia

  4. #4
    Guest

    Predefinito

    Allora, a parer mio ci sono diverse cose che potrebbero portarti a quella situazione
    di "morte apparente" dei processi.

    ...
    //Ciclo infinito di ascolto
    //-------------------------
    while(1) {

    if ((temp_sd=accept(sd,(struct sockaddr *)&client,&address_size)) < 0)[INDENT]{
    printf ("Errore durante la chiamata ACCEPT\n");
    exit(-1);
    }

    ...

    if (pid == 0) { //ci troviamo nel figlio

    close(sd); // Questo è sbagliato. Il descrittore del socket di
    // listening deve rimanere vivo se vuoi che continui
    // ad accettare connessioni in ingresso

    ...

    printf ("Dati ricevuti : %s\n",dati_ricevuti);
    close(temp_sd);

    exit(0);
    }

    else { //Mi trovo nel padre

    close(temp_sd); // Non c'è alcun motivo di chiudere il socket
    // in quanto ci hai già pensato nel processo
    // figlio.
    }


    }
    exit(0);

    Tieni presente che con la chiamata fork i descrittori del processo figlio
    sono ereditati pari pari dal processo padre, di conseguenza se chiudi la connessione
    da uno dei due processi la "chiudi anche per l'altro" in quanto i due descrittori (temp_sd o
    sd a seconda del caso) si riferiscono alla stessa connessione TCP.
    Prova a togliere.
    Un altro consiglio che ti posso dare è quello di cercare sempre di chiudere le connessioni
    in modo "graceful", ovvero usando la seguente combinazione di funzioni:

    shutdown(sck, SHUT_RDWR);
    ret = close(sck);

    Fammi sapere se ti è stato di aiuto.

  5. #5
    L'avatar di radioradianti
    radioradianti non è connesso Utente storico
    Data registrazione
    26-11-2003
    Residenza
    Roma
    Messaggi
    1,000

    Predefinito

    Citazione Originalmente inviato da dndvault

    ...

    if (pid == 0) { //ci troviamo nel figlio

    close(sd); // Questo è sbagliato. Il descrittore del socket di
    // listening deve rimanere vivo se vuoi che continui
    // ad accettare connessioni in ingresso

    ...

    printf ("Dati ricevuti : %s\n",dati_ricevuti);
    close(temp_sd);

    exit(0);
    }

    else { //Mi trovo nel padre

    close(temp_sd); // Non c'è alcun motivo di chiudere il socket
    // in quanto ci hai già pensato nel processo
    // figlio.
    }


    }
    exit(0);

    Tieni presente che con la chiamata fork i descrittori del processo figlio
    sono ereditati pari pari dal processo padre, di conseguenza se chiudi la connessione
    da uno dei due processi la "chiudi anche per l'altro" in quanto i due descrittori (temp_sd o
    sd a seconda del caso) si riferiscono alla stessa connessione TCP.
    Prova a togliere.
    Un altro consiglio che ti posso dare è quello di cercare sempre di chiudere le connessioni
    in modo "graceful", ovvero usando la seguente combinazione di funzioni:

    shutdown(sck, SHUT_RDWR);
    ret = close(sck);

    Fammi sapere se ti è stato di aiuto.
    ho apportato le modifiche che mi hai detto, compreso lo shutdown, ma il problema non è stato risolto, i defunti ci sono ancora.

    I processi sono ora in CLOSE_WAIT e non in TIME_WAIT, ma gli zombie sono sempre li

    E' on line il numero 12 di Topolinux - Totalmente rinnovato!
    TopoLinux è anche chat! irc.azzurra.org canale #topolinux
    La semplicità di questo dono è inversamente proporzionale alla qualità della nostra amicizia

  6. #6
    Guest

    Predefinito

    Ok, dovrebbe essere giusto che rimangano in close_wait. Quando hai creato i socket, hai abilitato i KeepAlive?

    Per farlo prova con il seguente codice:
    SOCKET tmpSck;
    struct sockaddr_in serverAddr;
    int keepValue;
    int retVal;

    ....

    tmpSck = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); /* Creazione socket */
    if (tmpSck == SCK_ERROR)
    {
    printf("Impossibile creare il socket\n");
    *sck = SCK_NULL;
    return SCK_ERROR;
    }
    /* Parametri del socket */
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(25);
    serverAddr.sin_addr.s_addr = inet_addr(serverAddress);

    keepValue = 1;
    retVal = setsockopt(tmpSck, SOL_SOCKET, SO_KEEPALIVE, (char *) &keepValue, sizeof(keepValue));
    if (retVal != 0)
    {
    KillSocket(tmpSck);
    *sck = SCK_NULL;
    return SCK_ERROR;
    }

    E' giusto un esempio, quindi vedi di riadattarlo al tuo caso, comunque la parte importante è quella che effettua la setsockopt abilitando i keepalive.

    Al solito, fammi sapere che risultati hai avuto.

  7. #7
    Ospite Guest

    Predefinito

    close(temp_sd); nel padre e close(sd); nel figlio, sono giusti, servono per evitare di sdoppiare il socket in listening e quello di connessione
    ma i vari exit(0) sparsi nel programma sono proprio necessari??

  8. #8
    L'avatar di radioradianti
    radioradianti non è connesso Utente storico
    Data registrazione
    26-11-2003
    Residenza
    Roma
    Messaggi
    1,000

    Predefinito

    Citazione Originalmente inviato da xDestroyer
    close(temp_sd); nel padre e close(sd); nel figlio, sono giusti, servono per evitare di sdoppiare il socket in listening e quello di connessione
    ma i vari exit(0) sparsi nel programma sono proprio necessari??
    probabilmente non sono necessari, ma nn credo che risolvano il mio problema. :sadOLD:

    Girovagando nella rete ho trovato 2 funzioni che sembra possano aiutarmi :

    waitpid
    e
    Tcl_WaitPid

    la prima l'ho provata e diciamo che più o meno funziona, nel senso che gli zombie spariscono, ma il server non accetta nuove connessioni finche il figlio nn muore.

    La seconda invece, da quello che ho capito lavora in background, quindi in teoria dovrebbe rimuovere lo zombie ,nel caso si presenti, senza interferire con il server stesso.
    Putroppo nn sono riuscito ancora a farla fuzionare, ma nn dispero!

    Happy Slack!

    Leandro

    E' on line il numero 12 di Topolinux - Totalmente rinnovato!
    TopoLinux è anche chat! irc.azzurra.org canale #topolinux
    La semplicità di questo dono è inversamente proporzionale alla qualità della nostra amicizia

Regole di scrittura

  • Non puoi creare nuove discussioni
  • Non puoi rispondere ai messaggi
  • Non puoi inserire allegati.
  • Non puoi modificare i tuoi messaggi
  •