summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2011-01-22 23:06:52 +0000
committerLudovic Pouzenc <ludovic@pouzenc.fr>2011-01-22 23:06:52 +0000
commit31f0e4b4067901e35ba3c3c66a77e84f35e74992 (patch)
tree70327d37a44f85b8001c7fdf590a53f90b8948e1
parentd26dbab8f789d787d5c39f8700b4ac19701f286f (diff)
download2011-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
-rw-r--r--app/v3_c/src/CMakeLists.txt2
-rw-r--r--app/v3_c/src/include/process.h13
-rw-r--r--app/v3_c/src/myhttpd.c94
-rw-r--r--app/v3_c/src/process.c33
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;
+}