#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <signal.h>
#define TAILLE_BUF 128
int descServ;
void panic (const char *msg) {
perror(msg);
exit(1);
}
void fin (int sig) {
int descServ;
if (close (descServ) != -1)
printf("Descripteur bien fermé\n");
exit(0);
}
int main (int argc, char *argv[]) {
int descServ;
int descClient;
int len;
int lg_addr_client = sizeof(struct sockaddr_in);
int lgMsg = TAILLE_BUF;
struct sockaddr_in addrServ;
struct sockaddr_in addrClient;
char *buf = (char*) malloc (TAILLE_BUF);
struct sigaction act;
descServ = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//Quitter proprement par ^C
act.sa_handler = fin;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGINT, &act,0);
//Ignorer la mort des fils
signal(SIGCHLD,SIG_IGN);
//nommage du serv
addrServ.sin_family = AF_INET;
addrServ.sin_addr.s_addr = htonl(INADDR_ANY); //toutes les adresses possibles du serveur !
addrServ.sin_port = htons(0);
if (bind (descServ,(struct sockaddr *) &addrServ,(sizeof(struct sockaddr_in))) == -1)
panic("Erreur de nommage");
if (getsockname (descServ,(struct sockaddr *) &addrServ,&len) == -1)
panic("Erreur lors de la recuperation du port");
//Affichage des infos serveurs a communiquer aux clients
printf("Infos sur le serveur:\n");
printf("\tPort: %d\n",ntohs(addrServ.sin_port));
//reception des messages des clients:
listen (descServ,5); //crée une liste d'attente
//SOMAXCONN est la valeur max du systeme
for(;;) {
printf("serveur en attente d'un message\n");
descClient = accept (descServ,(struct sockaddr *) &addrClient,&lg_addr_client);
if (descClient == -1)
panic("Connection ratée");
switch (fork()) {
case -1:
panic ("Duplication ratée");
case 0:
read(descClient,buf,TAILLE_BUF);
//simule un long traitement de données
sleep(2);
printf("Message %s recu de %s sur port %d \n",buf,inet_ntoa(addrClient.sin_addr),ntohs(addrClient.sin_port));
write(descClient,"Requete bien traitée",20);
close(descClient);
exit(0);
default:
close(descClient);
}
}
}
/*
Rendu possible car il ya recopie de l'espace d'adressage
et aussi de la table des descripteurs ouverts lors d'un fork()
Attention ne marcherait pas avec une thread -> car l'acceptation
d'un nouveau client ecraserait le descripteur client (partagé)
Résultat:
$ serveur
serveur en attente d'un message
-> Attente 2 secondes
Message Bonjour1 recu de 127.0.0.1 sur port 1058
serveur en attente d'un message
-> Attente 2 secondes
Message Bonjour2 recu de 127.0.0.1 sur port 1059
serveur en attente d'un message
-> Attente 2 secondes
Message Bonjour3 recu de 127.0.0.1 sur port 1060
$ serveur-fork
serveur en attente d'un message
serveur en attente d'un message
serveur en attente d'un message
serveur en attente d'un message
-> Attente 2 secondes
Message Bonjour1 recu de 127.0.0.1 sur port 1062
Message Bonjour2 recu de 127.0.0.1 sur port 1063
Message Bonjour3 recu de 127.0.0.1 sur port 1064
*/
syntax highlighted by Code2HTML, v. 0.9.1