diff options
author | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2011-01-22 23:06:52 +0000 |
---|---|---|
committer | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2011-01-22 23:06:52 +0000 |
commit | 31f0e4b4067901e35ba3c3c66a77e84f35e74992 (patch) | |
tree | 70327d37a44f85b8001c7fdf590a53f90b8948e1 /app/v3_c | |
parent | d26dbab8f789d787d5c39f8700b4ac19701f286f (diff) | |
download | 2011-usi-31f0e4b4067901e35ba3c3c66a77e84f35e74992.tar.gz 2011-usi-31f0e4b4067901e35ba3c3c66a77e84f35e74992.tar.bz2 2011-usi-31f0e4b4067901e35ba3c3c66a77e84f35e74992.zip |
Avancement sur le serveur web en C.
Le fichier myhttpd.c conteint à présent un serveur TCP/IP complet qui accepte des connexions et appelle requestProcess() et process.c qui lui doit décider de passer la main à un thread ou faire la mise en attente..
git-svn-id: file:///var/svn/2011-usi/trunk@14 db941bf7-0cb3-4dda-9634-87faf64f93a7
Diffstat (limited to 'app/v3_c')
-rw-r--r-- | app/v3_c/src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | app/v3_c/src/include/process.h | 13 | ||||
-rw-r--r-- | app/v3_c/src/myhttpd.c | 94 | ||||
-rw-r--r-- | app/v3_c/src/process.c | 33 |
4 files changed, 128 insertions, 14 deletions
diff --git a/app/v3_c/src/CMakeLists.txt b/app/v3_c/src/CMakeLists.txt index 2947cb3..4a85291 100644 --- a/app/v3_c/src/CMakeLists.txt +++ b/app/v3_c/src/CMakeLists.txt @@ -7,6 +7,6 @@ configure_file ( "${PROJECT_BINARY_DIR}/myhttpd.h" ) -add_executable(myhttpd myhttpd.c ${SRC_COMMON} ) +add_executable(myhttpd myhttpd.c process.c ${SRC_COMMON} ) #target_link_libraries(netlem SDL SDL_net SDL_image) diff --git a/app/v3_c/src/include/process.h b/app/v3_c/src/include/process.h new file mode 100644 index 0000000..c88b235 --- /dev/null +++ b/app/v3_c/src/include/process.h @@ -0,0 +1,13 @@ +#ifndef PROCESS_H +#define PROCESS_H + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +int initProcess(); +int requestProcess(int sockfd, struct sockaddr_in *addr, socklen_t *addrlen ); +void freeProcess(); + +#endif diff --git a/app/v3_c/src/myhttpd.c b/app/v3_c/src/myhttpd.c index 1e0c3e8..9d77949 100644 --- a/app/v3_c/src/myhttpd.c +++ b/app/v3_c/src/myhttpd.c @@ -2,25 +2,44 @@ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> - #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <errno.h> +#include <unistd.h> +#include <signal.h> #include "myhttpd.h" +#include "process.h" #include "utils.h" +int end=0; + +void signals(int signum) { + static int force=0; + + if (0) printf("signal %i\n"); + + if(!force) { + end=1; + force=1; + logs("Tentative d'arrêt soft du serveur..."); + } else { + logs("Arrêt d'urgence du serveur"); + exit(1); + } +} + + int main() { int res; int sockServ, sockCli; struct sockaddr_in servAddr, cliAddr; - size_t cliAddrLen; - int ending; + socklen_t cliAddrLen; // Création socket sockServ = socket(AF_INET, SOCK_STREAM, 0); - if (sockServ < 0) { perror("socket"); exit(1); } + if (sockServ < 0) { perror("socket"); return(2); } // Accrochage du socket (adresse et port locaux) bzero((char *) &servAddr, sizeof(servAddr)); @@ -28,21 +47,70 @@ int main() { servAddr.sin_addr.s_addr = INADDR_ANY; servAddr.sin_port = htons(LISTEN_PORT); res=bind(sockServ, (struct sockaddr *) &servAddr, sizeof(servAddr)); - if (res < 0) { perror("bind"); exit(2); } + if (res < 0) { perror("bind"); return(3); } - // On la:nce l'écoute + // On lance l'écoute listen(sockServ,LISTEN_BACKLOG); - if (res < 0) { perror("listen"); exit(3); } + if (res < 0) { perror("listen"); return(4); } + + // On active la gestion des signaux + signal(2,signals); + + res=initProcess(); + if (res != 0 ) { +#ifdef DEBUG + logs("initProcess() error"); +#endif + return(5); + } // Boucle d'acceptation des clients cliAddrLen = sizeof(cliAddr); - ending=0; - while ( ! ending ) { + while ( ! end ) { + // Appel bloquant d'acceptation d'un nouveau client sockCli=accept(sockServ, (struct sockaddr *) &cliAddr, &cliAddrLen); - #ifdef DEBUG - logs("Client accepté"); - #endif - + + // Il y plein de raisons pour qu'un accept echoue + if (sockCli < 0) { + switch(errno) { + case EAGAIN: + case EINTR: + // Cas qui ne sont pas des erreurs, mais nécessitent de rappeler accept +#ifdef DEBUG + perror("accept (info)"); +#endif + break; + case EMFILE: + case ENFILE: + case ENOBUFS: + case ENOMEM: + // Cas d'erreur transitoire (attente d'une seconde histoire d'attendre un peu si ressources fichiers, ram épuisés +#ifdef DEBUG + perror("accept (warn)"); + sleep(1); +#endif + break; + default: + // Cas d'erreur fatales + perror("accept (err)"); + end=2; + } + } else { + // Cas nominal : un nouveau socket est disponible avec un client au bout +#ifdef HEAVYDEBUG + logs("Client accepté"); +#endif + end=requestProcess(sockCli, &cliAddr, &cliAddrLen); + } + } + + freeProcess(); + + if ( end != 1 ) { +#ifdef DEBUG + logs("Fin anormale du serveur"); +#endif + return(6); } return 0; diff --git a/app/v3_c/src/process.c b/app/v3_c/src/process.c new file mode 100644 index 0000000..630c718 --- /dev/null +++ b/app/v3_c/src/process.c @@ -0,0 +1,33 @@ +#include <stdlib.h> +#include <unistd.h> + +#include "process.h" +#include "utils.h" + +int initProcess() { + // Créer au départ toutes les zones mémoire à gérer + pool de threads + files de sockets en attente... + // Utiliser des déclarations globales dans ce fichier et gérer la concurrence entre les threads + + return 0; +} + +// Appelé des qu'un nouveau socket client est créé via accept(). +// Un retour non nul de cette fonction provoque l'arrêt du serveur http +int requestProcess(int sockfd, struct sockaddr_in *addr, socklen_t *addrlen ) { +#ifdef HEAVYDEBUG + logs("requestProcess start"); +#endif + if ( 0 ) { printf("%i %p %p\n", sockfd, (void *)addr, (void *)addrlen); } + + + close(sockfd); +#ifdef HEAVYDEBUG + logs("requestProcess end"); +#endif + return 0; +} + +void freeProcess() { + // Libérer tous les espaces histoire de voir des infos propres dans valgrind + return; +} |