|
TCP Socket - C Language
|
#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 |
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.
| #define MAXSRVSLEEP 128 |
| 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.
| sig | codice del segnale ricevuto |
| 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;
}