Académique Documents
Professionnel Documents
Culture Documents
{
/* Si probleme de lecture sur la socket (fermee brutalement
Documentation : lire les pages de manuel suivantes : (r)syslogd, (r)syslog.conf
* par exemple) */
if (nb_lu == -1 || nb_lu == 0)
{
Créer un répertoire /local/TP5 et mettez les fichiers suivants :
return ;
}
– repeteur.c;
– Makefile
/* On repete ce qui a ete dit et on renvoie au client : si ça marche pas met
repeteur.c est un programme démon "répétant" tout ce qu’on lui dit. Il tourne sur le port « return » à la place du code en bleu (les 4 lignes en bleu */
6666 et reste à l’écoute d’une éventuelle connexion. Le protocole utilisé est du TCP. if (strncmp("stop\r\n",buf,6)==0)
{ openlog(“repeater”, LOG_PID | LOG_CONS, LOG_LOCAL0);
– création du démon : duplication et détachement du processus parent, changement du syslog(LOG_INFO |LOG__ERROR, “deconnexion” );
masque, et du répertoire racine, fermeture des entrées, sorties et erreurs standards... closelog();
– initialisation des variables utilisées pour la partie réseau, attente sur le port 6666. kill(getpid(), SIGTERM);
– lorsqu’il y a demande de connexion, le processus est dupliqué et se charge du client: }
tant que le client ne se déconnecte pas, tout ce que le client enverra via cette socket write (socket_cliente, buf, nb_lu) ;
au serveur sera renvoyé à ce même client. }
}
***
Exercice 1 : Puis, par l’appel syslog, demande à syslogd d’enregistrer l’adresse IP du client ayant
effectué cette demande de fin de connexion, ainsi qu’une phrase indiquant que la
Compilez et lancez le programme repeteur.c, vérifier sa bonne marche en lançant dans connexion a été interrompue à la demande du client.
Plusieurs terms des telnet contactant le serveur. Vous aurez à modifier le fichier /etc/rsyslog.conf. Pour cela, vous rajouterez une facilité de
type local0 qui trace tous les messages quelque soit le niveau dans un fichier
Recopier les fichiers repeteur..c et Makefile dans le même répertoire /var/log/local0.log1
Puis faire make ou make all
Lancer ./repeteur Analysez l’affichage de netstat -ap
Appeler telnet localhost (ou chez le voisin) 6666 après écrire une chaîne et taper entrer,
la chaîne sera réaffichée Création d’un fichier lolal0.log dans /var/log
chmod local0.log 700
1 2
*/ setsid () ;
void repeter (int socket_cliente, struct sockaddr_in ) ; /*RHA add param struct /* 7 - Si le demon s'arrete, alors on sort du processus fils. Le
sockaddr_in */ * programme est alors termine. */
int lecture_socket (int socket_cliente, char *buf) ; exit (1) ;
default :
/*********************************************************************** /* Le processus pere est tue. On rend la main au shell appelant. */
* exit (0) ;
* }
* Fonction principale : return 0 ;
* On cree le demon en dupliquant le processus afin de detacher le }
* programme du processus pere
* /***********************************************************************
*
************************************************************************/ *
int main () * Le programme 'demon'
{ *
switch (fork ()) * Structure
{ * sockaddr_in : /usr/include/netinet/in.h
case -1 : *
perror ("*** erreur : fork impossible : demon non cree") ; *
exit (1) ; *
case 0 : ************************************************************************/
/* void demon ()
* Ce processus fils est celui qui deviendra le demon. {
* Ingredients pour en faire un vrai et bon demons : int socket_ecoute ;
*/ int socket_cliente ;
/* 1 - On cree une nouvelle session. Pas de terminal de controle */ int valeur_retour ;
3 4
int salong ; break ;
int opt = 1 ;
struct sockaddr_in monadr, sonadr ; case 0 :
int status ;
repeter (socket_cliente, sonadr) ; /*RHA add param sonadr*/
close (socket_cliente) ;
/* kill (getpid(),SIGTERM);
* Creation de la socket d'ecoute
*/ default :
socket_ecoute = socket (PF_INET, SOCK_STREAM, 0) ; waitpid (-1, &status, WNOHANG);
close (socket_cliente) ;
/* }
* Modification des options associees a la socket d'ecoute. }
*/ }
setsockopt (socket_ecoute, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, \
sizeof (opt)) ; /***********************************************************************
*
/* *
* Initialisation des parametres internet de la socket d'ecoute. * La fonction qui repete
*/ *
bzero ((char *) &monadr, sizeof monadr) ; *
monadr.sin_family = AF_INET ; *
monadr.sin_port = htons (PORT_REPETEUR) ;
monadr.sin_addr.s_addr = INADDR_ANY ; ************************************************************************/
valeur_retour = bind (socket_ecoute, (struct sockaddr *) &monadr, \ void repeter (int socket_cliente, struct sockaddr_in sock_addr) /*RHA add 2nd
(int) sizeof monadr) ; param*/
{
/* int nb_lu ;
* Socket mise en position d'ecoute ('listen'). On specifie aussi le char buf [MAXLEN] ;
* nombre de connexions simultanees acceptees. char * addr; /*RHA declare addr*/
*/
valeur_retour = listen (socket_ecoute, NB_CONN_MAX) ;
addr = inet_ntoa(sock_addr.sin_addr);
/**
* Le demon tourne indefiniment a l'ecoute d'eventuelles connections while ((nb_lu = lecture_socket (socket_cliente, buf)) > 0)
* 'accept' {
* Lorsqu'un client se connecte, une socket est cree (socket_cliente). /* Si probleme de lecture sur la socket (fermee brutalement
* on duplique le processus et le processus fils prend en charge * par exemple) */
* cette socket par la fonction 'repeter'. if (nb_lu == -1 || nb_lu == 0)
*/ {
while (1) return ;
{ }
salong = sizeof sonadr ;
/* On repete ce qui a ete dit et on renvoie au client */
socket_cliente = accept (socket_ecoute, (struct sockaddr *) &sonadr, \
(socklen_t *) &salong) ; if (strncmp("stop\r\n",buf,6)==0){
syslog(LOG_LOCAL0, addr);
switch (fork ()) return;
{ }
case -1 :
5 6
write (socket_cliente, buf, nb_lu) ;
} int main(int argc, char **argv){
FILE *fp;
}
/* ouverture socket */
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
Exercice 3 : if (sockfd < 0)
error("ERROR opening socket");
Ecrivez un programme client parleur.c qui lit la première ligne d’un fichier, l’envoie au serveur,
attend la réponse du serveur et l’affiche, puis passe à la ligne suivante. //recuperer l'@ ip via le premier argument
server = gethostbyname(argv[1]);
if (server == NULL) {
Il y a deux codes que je n’ai pas testé fprintf(stderr,"ERROR, no such host\n");
Il faut faire en principe : exit(0);
Lancer le ./repeteur }
./parleur ip-de_serveur_repeteur port_du_serveur_nom_du_fichier
// initialisation a zero du buffer
./parleur
bzero((char *) &serv_addr, sizeof(serv_addr));
Premier code :
/************************************************************************** // remplir ip et port
*/ serv_addr.sin_family = AF_INET;
// bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,server-
// usage: >h_length);
// serv_addr.sin_port = htons(portno);
// ./parleur ip port nomfichier
// // socket connect
// ip : ip du serveur "repeteur" if (connect(sockfd, (stuct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
// port : port du serveur error("ERROR connecting");
// nomfichier: nom du fichier a envoyer
/**************************************************************************
***/ if ( fp != NULL )
#include <unistd.h>
#include <stdlib.h> {
#include <sys/stat.h>
#include <string.h> char line [ 128 ]; /* or other suitable maximum line size */
#include <stdio.h>
7 8
printf("entre temps : %s \n",line); #include <syslog.h>
#include <signal.h>
// lecture du socket
n = read(sockfd,line,128);
if (n < 0) #define MAXLEN 1024
error("ERROR reading from socket"); #define PORT_REPETEUR 6666
#define NB_CONN_MAX 5
printf(" j'ai reçu : %s \n",line);
//printf("ligne : %s",line);
int main(int argc, char **argv){
FILE *fp;
}
fclose ( fp);
}
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
return 0;
}
/* ouverture fichier */
fp=fopen(argv[3],"r");
9 10
{
#include <signal.h>
}
fclose ( fp); #include <arpa/inet.h> /* inclusion de la biblio nécessaire à l'usage des fonctions inet*/
} #define MAXLEN 1024
#define PORT_REPETEUR 6666
#define NB_CONN_MAX 5
void demon () ;
return 0;
} void repeter (int socket_cliente, struct sockaddr_in sock_addr) ;
Fin code 2 int lecture_socket (int socket_cliente, char *buf) ;
void signal_contrC(int sig); /* EXERCICE4 */
/************************************************************************
*
* Fonction principale :
* On cree le demon en dupliquant le processus afin de detacher le
* programme du processus pere
Exercice 4 : *
Modifiez le programme repeteur.c afin qu’une interruption par l’administrateur du serveur soit ************************************************************************/
récupérée, tracée par syslog et coupe proprement la connexion avec chacun des clients en cours int main ()
avant de s’arrêter. {
signal(SIGTERM,signal_contrC); /* EXERCICE 4 */
11 12
switch (fork ()) * sockaddr_in : /usr/include/netinet/in.h
{ *
case -1 : *
perror ("*** erreur : fork impossible : demon non cree") ; *
exit (1) ;
************************************************************************/
case 0 : void demon ()
/* {
* Ce processus fils est celui qui deviendra le demon. int socket_ecoute ;
* Ingredients pour en faire un vrai et bon demons : int socket_cliente ;
*/ int valeur_retour ;
/* 1 - On cree une nouvelle session. Pas de terminal de controle */ int salong ;
setsid () ; int opt = 1 ;
struct sockaddr_in monadr, sonadr ;
/* 2 - le repertoire courant est change a la racine afin de ne pas int status ;
* causer de probleme lors de demontage eventuel de partition
*/
chdir ("/") ; /*
* Creation de la socket d'ecoute
/* 3 - Le masque sur les droits lors de creation de fichiers */ */
umask (0) ; socket_ecoute = socket (PF_INET, SOCK_STREAM, 0) ;
default : /*
/* Le processus pere est tue. On rend la main au shell appelant. */ * Socket mise en position d'ecoute ('listen'). On specifie aussi le
exit (0) ; * nombre de connexions simultanees acceptees.
} */
return 0 ; valeur_retour = listen (socket_ecoute, NB_CONN_MAX) ;
}
/**
/************************************************************************ * Le demon tourne indefiniment a l'ecoute d'eventuelles connections
* * 'accept'
* Le programme 'demon' * Lorsqu'un client se connecte, une socket est cree (socket_cliente).
* * on duplique le processus et le processus fils prend en charge
* Structure * cette socket par la fonction 'repeter'.
13 14
*/ {/*syslog(LOG_LOCAL0, addr);*/
while (1)
{
salong = sizeof sonadr ; //On spécifie l'information à l'utilisateur
write (socket_cliente, "\nFermeture de la connexion a la demande du client\n", 50);
socket_cliente = accept (socket_ecoute, (struct sockaddr *) &sonadr, \ //On récupère son adresse IP
(socklen_t *) &salong) ;
char* addr = inet_ntoa(sock_addr.sin_addr);
switch (fork ()) //On logue le tout dans le fichier /var/log/local0.log
{ openlog("repeteur",0,LOG_LOCAL0);
case -1 : syslog(LOG_LOCAL0,"arret de la connexion par %s",addr);
break ; closelog();
return;
case 0 : }
repeter (socket_cliente, sonadr) ;
close (socket_cliente) ;
//kill (getpid(),SIGTERM);
default :
waitpid (-1, &status, WNOHANG); /* On repete ce qui a ete dit et on renvoie au client */
close (socket_cliente) ; write (socket_cliente, buf, nb_lu) ;
} }
} } /* Solution EXERCICE 2 pour le log */
}
int lecture_socket (int socket_cliente, char *buf)
/************************************************************************ {
* int nb_lu ;
* La fonction qui repete
* nb_lu = read (socket_cliente, buf, MAXLEN) ;
*
* return (nb_lu) ;
}
************************************************************************/ //procedure signal /* Solution EXERCICE 4 pour coupure */
void repeter (int socket_cliente, struct sockaddr_in sock_addr) void signal_contrC(int sig)
{ {
int nb_lu ; openlog("repeteur",0,LOG_LOCAL0);
char buf [MAXLEN] ; syslog(LOG_LOCAL0,"coupure de la connexion par l'administrateur \n");
char *addr; closelog();
printf("\ncoupure de la connexion par l'administrateur, dsl.\n");
while ((nb_lu = lecture_socket (socket_cliente, buf)) > 0) exit(EXIT_SUCCESS);
{ } /* Solution EXERCICE 4 pour coupure */
/* Si probleme de lecture sur la socket (fermee brutalement
* par exemple) */
if (nb_lu == -1 || nb_lu == 0)
{
return ;
}
/*on caompare sur 6 caracteère la chaine que l'utilisateur envoie à la taille du buffeur*/
/* Solution EXERCICE 2 pour le log */
if (strncmp("stop\r\n",buf,6)==0)
15 16