TCP Socket - C Language
Riferimenti per il file server.c
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include "pool.h"
#include "comm.h"
#include "errore.h"

Vai al codice sorgente di questo file.

Definizioni

#define MAXSRVSLEEP   128

Funzioni

void * client_comm (void *sk)
void gestore (int sig)
int main (int argc, char *argv[])

Variabili

volatile sig_atomic_t quitflag

Descrizione dettagliata

Autore:
Tranchida Giulio, No Matricola 241732
Si dichiara che il contenuto di questo file e', in ogni sua parte, opera originale dell'autore.

This program is free software; you can redistribuite it and/or modify it under the terms of the GNU/General Pubblic License as published the Free software Foundation; either version 2 of the License, or (at your opinion) any later version.

Definizione nel file server.c.


Documentazione delle definizioni

#define MAXSRVSLEEP   128

Tempo di ritardo per l'inserimento di un nuovo job nel pool di thread nel caso di coda dei lavori piena: 128 => 2 minuti.

Definizione alla linea 22 del file server.c.


Documentazione delle funzioni

void * client_comm ( void *  sk)

Funzione che si occupa della reale comunicazione con il client

Definizione alla linea 123 del file server.c.

                            {
        int sk_cl;
        message_t msg;
        int recive_val = 1, sent_val = 1, quit = 0;

        sk_cl = *(int *)sk;
        msg.buffer = NULL;

        while ((recive_val>0) && (sent_val>0) && (quit!=1)){
                /* Ricevo un messaggio */
                if ((recive_val = receiveMessage(sk_cl, &msg)) > 1){
                        /* Controllo il tipo di messaggio ricevuto */
                        switch(msg.type){
                                case MSG_EXIT:
                                        quit = 1;
                                        msg.length = 0;
                                        if (msg.buffer) free(msg.buffer);
                                        msg.buffer = NULL;
                                        msg.type = MSG_OK;
                                break;
                                case MSG_PRINT:
                                        if (msg.buffer){
                                                printf ("Mgs: %s\n",msg.buffer);
                                                free(msg.buffer);
                                        }
                                        msg.length = 0;
                                        msg.buffer = NULL;
                                        msg.type = MSG_OK;
                                break;
                        }
                        /* Invio il messaggio di risposta */
                        sent_val = sendMessage(sk_cl, &msg);
                }
        }

        printf("Server: Comunicazione con il client chiusa\n");
        /* Chiudo la socket di comunicazione */
        closeConnection(sk_cl);
        return 0;
}
void gestore ( int  sig)

Il mio gestore dei segnali
Stampa a monitor il codice del segnale ricevuto se questo e' SIGTERM o SIGINT e mette quitflag a 1, altrimenti se e' un SIGPIPE non fa nulla.

Parametri:
sigcodice del segnale ricevuto

Definizione alla linea 172 del file server.c.

                      {
        switch (sig) {
                case SIGTERM:
                        write(2, "server: signal 15 detected\n", 27);
                        quitflag = 1;
                break;
                case SIGINT:
                        write(2, "server: signal 2 detected\n", 26);
                        quitflag = 1;
                break;
        }
}
int main ( int  argc,
char *  argv[] 
)

Main di esempio del server

Definizione alla linea 32 del file server.c.

                               {
        int nsec;
        int cln_sk;                     
        th_pool * pool;         
        sigset_t poolset;       
        sigset_t set;           
        char * service = "12100";       
        comm * srvComm = NULL;
        struct sigaction action;
        quitflag = 0;

        /* ========= Gestione dei segnali ========= */
        /* Blocco i segnali */
        if (sigfillset(&set) == -1){
                sys_err(__FILE__,__LINE__,"Server: error sigfillset: ");
                return EXIT_FAILURE;
        }

        if (pthread_sigmask(SIG_SETMASK, &set, NULL) != 0) {
                sys_err(__FILE__,__LINE__,
                        "Server: pthread_sigmask error 'sigsetmask': ");
                return EXIT_FAILURE;
        }

        /* Installo il nuovo gestore */
        memset(&action, 0, sizeof(action));
        if (sigemptyset(&action.sa_mask) == -1){
                sys_err(__FILE__,__LINE__,"Server: error sigemptyset: ");
                return EXIT_FAILURE;
        }

        /* Ignoro il SIGPIPE */
        action.sa_handler = SIG_IGN;
        if (sigaction(SIGPIPE, &action, NULL) == -1) {
                sys_err(__FILE__,__LINE__, "Server: sigaction error 'SIGPIPE': ");
                exit(EXIT_FAILURE);
        }
        action.sa_handler = gestore;
        action.sa_flags = 0;

        /* Definisco i segnali che voglio gestire */
        if (sigaction(SIGINT, &action, NULL) < 0){
                sys_err(__FILE__,__LINE__,"Server: sigaction error 'SIGINT': ");
                return EXIT_FAILURE;
        }

        if (sigaction(SIGTERM, &action, NULL) < 0){
                sys_err(__FILE__,__LINE__,"Server: sigaction error 'SIGTERM': ");
                return EXIT_FAILURE;;
        }

        /* Installo la nuova maschera dei segnali */
        if (pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL) != 0) {
                sys_err(__FILE__,__LINE__,
                        "Server: pthread_sigmask error 'sigsetmask': ");
                return EXIT_FAILURE;
        }

        /* Questa maschera per il pool che ignora tutti i segnali */
        if (sigfillset(&poolset) == -1){
                sys_err(__FILE__,__LINE__,"Server: error sigfillset: ");
                exit(errno);
        }

        /* Creo una socket di comunicazione */
        if (!(srvComm = newServerChannel(service))){
                sys_err(__FILE__,__LINE__,"Server: createServerChannel: ");
                exit(errno);
        }

        /* Inizializzo un pool di thread di dimensione 5 e con
         * un numero massimo di job in attesa nella coda di 10 */
        pool = poolInit(5, 10, &poolset);

        while (!quitflag){
                /* Pongo il server in attesa di nuove connessioni */
                if ((cln_sk = acceptConnection(srvComm)) > 0){
                        /* Sottomissione job al pool con riprova (lenta) */
                        for (nsec = 1; nsec<=MAXSRVSLEEP && poolDispatcher(pool, client_comm, &cln_sk)==-5; nsec<<=1)
                                if (nsec<=MAXSRVSLEEP/2) sleep(nsec);
                }
                /* TODO Manca la gestione degli errori */
        }

        /* Arresto il pool di threads e libero le risorse */
        poolDestroy(pool);
        /* Chiudo la socket di comunicazione */
        closeServerSocket(srvComm);
        return 0;
}

Documentazione delle variabili

volatile sig_atomic_t quitflag

Variabile atomica per la terminazione del server

Definizione alla linea 25 del file server.c.