TCP Socket - C Language
server.c
Vai alla documentazione di questo file.
00001 
00011 #include <stdio.h>
00012 #include <unistd.h>
00013 #include <signal.h>
00014 
00015 #include "pool.h"
00016 #include "comm.h"
00017 #include "errore.h"
00018 
00022 #define MAXSRVSLEEP 128
00023 
00025 volatile sig_atomic_t quitflag;
00026 
00028 void *client_comm(void * sk);
00029 void gestore(int sig);
00030 
00032 int main(int argc,char* argv[]){
00033         int nsec;
00034         int cln_sk;                     
00035         th_pool * pool;         
00036         sigset_t poolset;       
00037         sigset_t set;           
00038         char * service = "12100";       
00039         comm * srvComm = NULL;
00040         struct sigaction action;
00041         quitflag = 0;
00042 
00043         /* ========= Gestione dei segnali ========= */
00044         /* Blocco i segnali */
00045         if (sigfillset(&set) == -1){
00046                 sys_err(__FILE__,__LINE__,"Server: error sigfillset: ");
00047                 return EXIT_FAILURE;
00048         }
00049 
00050         if (pthread_sigmask(SIG_SETMASK, &set, NULL) != 0) {
00051                 sys_err(__FILE__,__LINE__,
00052                         "Server: pthread_sigmask error 'sigsetmask': ");
00053                 return EXIT_FAILURE;
00054         }
00055 
00056         /* Installo il nuovo gestore */
00057         memset(&action, 0, sizeof(action));
00058         if (sigemptyset(&action.sa_mask) == -1){
00059                 sys_err(__FILE__,__LINE__,"Server: error sigemptyset: ");
00060                 return EXIT_FAILURE;
00061         }
00062 
00063         /* Ignoro il SIGPIPE */
00064         action.sa_handler = SIG_IGN;
00065         if (sigaction(SIGPIPE, &action, NULL) == -1) {
00066                 sys_err(__FILE__,__LINE__, "Server: sigaction error 'SIGPIPE': ");
00067                 exit(EXIT_FAILURE);
00068         }
00069         action.sa_handler = gestore;
00070         action.sa_flags = 0;
00071 
00072         /* Definisco i segnali che voglio gestire */
00073         if (sigaction(SIGINT, &action, NULL) < 0){
00074                 sys_err(__FILE__,__LINE__,"Server: sigaction error 'SIGINT': ");
00075                 return EXIT_FAILURE;
00076         }
00077 
00078         if (sigaction(SIGTERM, &action, NULL) < 0){
00079                 sys_err(__FILE__,__LINE__,"Server: sigaction error 'SIGTERM': ");
00080                 return EXIT_FAILURE;;
00081         }
00082 
00083         /* Installo la nuova maschera dei segnali */
00084         if (pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL) != 0) {
00085                 sys_err(__FILE__,__LINE__,
00086                         "Server: pthread_sigmask error 'sigsetmask': ");
00087                 return EXIT_FAILURE;
00088         }
00089 
00090         /* Questa maschera per il pool che ignora tutti i segnali */
00091         if (sigfillset(&poolset) == -1){
00092                 sys_err(__FILE__,__LINE__,"Server: error sigfillset: ");
00093                 exit(errno);
00094         }
00095 
00096         /* Creo una socket di comunicazione */
00097         if (!(srvComm = newServerChannel(service))){
00098                 sys_err(__FILE__,__LINE__,"Server: createServerChannel: ");
00099                 exit(errno);
00100         }
00101 
00102         /* Inizializzo un pool di thread di dimensione 5 e con
00103          * un numero massimo di job in attesa nella coda di 10 */
00104         pool = poolInit(5, 10, &poolset);
00105 
00106         while (!quitflag){
00107                 /* Pongo il server in attesa di nuove connessioni */
00108                 if ((cln_sk = acceptConnection(srvComm)) > 0){
00109                         /* Sottomissione job al pool con riprova (lenta) */
00110                         for (nsec = 1; nsec<=MAXSRVSLEEP && poolDispatcher(pool, client_comm, &cln_sk)==-5; nsec<<=1)
00111                                 if (nsec<=MAXSRVSLEEP/2) sleep(nsec);
00112                 }
00113                 /* TODO Manca la gestione degli errori */
00114         }
00115 
00116         /* Arresto il pool di threads e libero le risorse */
00117         poolDestroy(pool);
00118         /* Chiudo la socket di comunicazione */
00119         closeServerSocket(srvComm);
00120         return 0;
00121 }
00122 
00123 void *client_comm(void * sk){
00124         int sk_cl;
00125         message_t msg;
00126         int recive_val = 1, sent_val = 1, quit = 0;
00127 
00128         sk_cl = *(int *)sk;
00129         msg.buffer = NULL;
00130 
00131         while ((recive_val>0) && (sent_val>0) && (quit!=1)){
00132                 /* Ricevo un messaggio */
00133                 if ((recive_val = receiveMessage(sk_cl, &msg)) > 1){
00134                         /* Controllo il tipo di messaggio ricevuto */
00135                         switch(msg.type){
00136                                 case MSG_EXIT:
00137                                         quit = 1;
00138                                         msg.length = 0;
00139                                         if (msg.buffer) free(msg.buffer);
00140                                         msg.buffer = NULL;
00141                                         msg.type = MSG_OK;
00142                                 break;
00143                                 case MSG_PRINT:
00144                                         if (msg.buffer){
00145                                                 printf ("Mgs: %s\n",msg.buffer);
00146                                                 free(msg.buffer);
00147                                         }
00148                                         msg.length = 0;
00149                                         msg.buffer = NULL;
00150                                         msg.type = MSG_OK;
00151                                 break;
00152                         }
00153                         /* Invio il messaggio di risposta */
00154                         sent_val = sendMessage(sk_cl, &msg);
00155                 }
00156         }
00157 
00158         printf("Server: Comunicazione con il client chiusa\n");
00159         /* Chiudo la socket di comunicazione */
00160         closeConnection(sk_cl);
00161         return 0;
00162 }
00163 
00172 void gestore(int sig) {
00173         switch (sig) {
00174                 case SIGTERM:
00175                         write(2, "server: signal 15 detected\n", 27);
00176                         quitflag = 1;
00177                 break;
00178                 case SIGINT:
00179                         write(2, "server: signal 2 detected\n", 26);
00180                         quitflag = 1;
00181                 break;
00182         }
00183 }