Professional Documents
Culture Documents
2.3 La requte
Lors des cas de transfert de fichier (en envoi ou en rcupration), il est ncessaire de connatre la taille du fichier
transfr pour savoir si, lors d'un read dtectant une fin de fichier (d la fermeture de la connexion), tout le contenu a
bien t rcupr, ou si la connexion a t rompue trop tt.
Une requte est donc de la forme :
#define REQUETE_PUT 1
#define REQUETE_GET 2
#define REQUETE_DEL 3
#define REQUETE_DIR 4
G. BENAY 1 2007/2008
ESCPI TP 3 EI2
struct request {
int kind;
char path[MAXPATH];
int nbbytes; /* pour PUT seulement */
};
L'entier kind doit tre REQUETE_PUT, REQUETE_GET, REQUETE_DEL ou REQUETE_DIR. La chane path
contient le nom du fichier crire (put), lire (get), dtruire (del) ou lister (dir). L'entier nbbytes contient la taille du
fichier, lors d'un PUT seulement.
2.4 La rponse
Une rponse contient donc l'accus (ack). Si la rponse est positive (ack vaut ANSWER_OK) et que la requte tait
un GET, nbbytes contient la taille du fichier que le serveur va envoyer. Si la rponse est ngative (ANSWER_ERROR),
errnum contient le code de l'erreur (valeur de la variable errno).
#define ANSWER_OK 0
#define ANSWER_UNKNOWN 1 /* requete inconnue */
#define ANSWER_ERROR 2 /* erreur lors du traitement */
struct answer {
int ack;
int nbbytes; /* pour GET seulement */
int errnum; /* significatif ssi != 0 et ack == ANSWER_ERROR */
};
G. BENAY 2 2007/2008
ESCPI TP 3 EI2
3 Rappels sockets
Un socket est un point de communication par lequel le processus peut mettre ou recevoir des informations vers ou
en provenance d'un autre socket.
Serveur Client
Cration et attachement
d'une socket d'coute
socket()
Cration de la socket
cliente
Le serveur cre Cration du service
un fils pour bind() socket()
traiter les Le serveur passe en mode coute
requtes et lui il peut accepter des demandes de connexion
mme se remet
l'coute listen() bind()
Demande de connexion
accept() connect()
fork()
close() close()
struct sockaddr_in {
short sin_family; /* la famille de protocole */
u_short sin_port; /* numero de port */
struct in_addr sin_addr; /* adresse IP de la machine */
char sin_zero[8]; /* remplissage pour faire 16 octets */
};
Rappel : L'adresse IP d'une machine (type struct in_addr) est en fait 4 octets, qu'on crit gnralement sous la
forme 147.127.64.7.
G. BENAY 3 2007/2008
ESCPI TP 3 EI2
On utilise des sockets dans la famille de protocole Internet, de type stream (fiable, fifo, bi-directionnel), crs par :
socket (PF_INET, SOCK_STREAM, 0). Pour la connexion (serverhost est le nom de la machine que l'on
veut contacter, port est le numro du port sur cette machine) :
{ int sc;
struct hostent *sp;
struct sockaddr_in sins;
/* Obtention d'information au sujet de la machine `serverhost' */
sp = gethostbyname (serverhost);
if (sp == NULL) {
fprintf (stderr, "gethostbyname: %s not found\n", serverhost);
exit (1);
}
/* Creation d'un socket Internet de type stream (fiable, bi-directionnel)
*/
sc = socket (PF_INET, SOCK_STREAM, 0);
if (sc == -1) {
perror ("socket failed");
exit (1);
}
/* Remplissage de la structure `sins' avec la famille de protocoles
Internet,
* le numero IP de la machine a contacter et le numero de port. */
sins.sin_family = AF_INET;
memcpy (&sins.sin_addr, sp->h_addr_list[0], sp->h_length);
sins.sin_port = htons (port);
/* Tentative d'etablissement de la connexion. */
if (connect (sc, (struct sockaddr *)&sins, sizeof(sins)) == -1) {
perror ("connect failed");
exit (1);
}
}
Ce qui s'utilise (port est le numro du port sur lequel coute le serveur) :
{ struct sockaddr_in soc_in;
int val;
int ss;
G. BENAY 4 2007/2008
ESCPI TP 3 EI2
while (1) {
struct sockaddr_in from;
int len;
int f;
/* ... */
}
}
Attention : il manque le traitement d'erreur, qui est indispensable avec les sockets, du fait de la forte probabilit de
dfaillance.
4 Rappels Unix
Tous les appels systmes renvoient -1 en cas d'erreur. Dans ce cas, la variable errno contient le code de l'erreur.
4.1 Obtenir des informations sur un fichier : stat
Pour obtenir des information sur un fichier, utiliser :
La structure struct stat contient de nombreux champs (voir man stat pour plus de dtails), dont st_uid
(propritaire du fichier), st_size (taille du fichier), st_mode (droit d'accs), st_mtime (date de dernire
modification)...
#include <sys/types.h>
#include <sys/stat.h>
main (int argc, char **argv)
{
struct stat buf;
if (stat (argv[1], &buf) == -1)
perror (argv[1]);
else
printf ("%s: proprietaire %d, taille %d\n", argv[1], buf.st_uid,
buf.st_size);
}
La premire ligne ouvre le fichier en lecture ; la deuxime ouvre le fichier pour criture, avec cration s'il n'existe
pas et troncature s'il existe dj ; la troisime ligne ouvre le fichier pour criture, avec cration s'il n'existe pas et erreur
s'il existe dj. Le troisime argument est utilis pour dfinir les droits d'accs (ici rw-r--r--) s'il y a cration du
G. BENAY 5 2007/2008
ESCPI TP 3 EI2
fichier.
4.3 Destruction d'un fichier unlink
L'appel systme :
int unlink (char *pathname);
dtruit le lien spcifi par pathname. Si ce lien tait le dernier lien vers le fichier, le fichier est effac.
4.4 Lecture/criture read /write
int read (int fd, void *buf, int nbyte);
int write (int fd, const void *buf, int nbyte);
L'appel systme read lit sur le descripteur au plus nbyte octets et les range l'adresse buf. Il renvoie le nombre
d'octets effectivement lus, ou 0 si la fin de fichier a t atteinte (il n'y a et il n'y aura plus rien lire : socket ferm ou
fichier compltement lu), ou -1 en cas d'erreur.
L'appel systme write crit sur le descripteur au plus nbyte octets rangs l'adresse buf. Il renvoie le nombre
d'octets effectivement crits, ou -1 en cas d'erreur.
Quand read ou write sont appliqus un fichier, le nombre d'octets lus ou crits est toujours le nombre demand
(sauf lorsque la fin du fichier est atteinte) ; quand ils sont appliqus un descripteur associ un socket, le nombre
d'octets lus ou crits peut tre infrieur au nombre demand.
4.5 Les signaux
Un signal est un vnement asynchrone auquel il est possible d'associer un traitement spcifique (une procdure qui
sera invoque par le systme la dlivrance du signal). En absence de traitement, un signal entrane en gnral la mort
du processus destinataire. L'association d'un traitement se fait au moyen de la primitive signal :
void traitement_sig (int sig)
{
signal (SIGCHLD, traitement_sig); /* remise en place du traitement */
...
}
...
main()
{
...
signal (SIGCHLD, traitement_sig);
...
}
G. BENAY 6 2007/2008
ESCPI TP 3 EI2
1. Personne seule
TP3ReseauNomGrooupeEI2Nom.zip
NomGrooupeEI2: le nom du groupe EI2 (EI2AD, EI2AG, ou EI-I2B)
Nom1 votre nom si seul,
2. Binme
TP3ReseauNomGrooupeEI2Nom1Nom2.zip
NomGrooupeEI2 : le nom du groupe EI2 (EI2AD, EI2AG, ou EI-I2B)
Nom1 le nom d'un des membres du binme
Nom2 le nom de l'autre membre du binme
Vous envoyez votre rapport par courrier lectronique l'adresse : gerard.benay@cnam.frau plus
tard le :
EII2AG:Vendredi6juin2008
EII2AD:Vendredi30mai2008
EII2B:Vendredi30mai2008
G. BENAY 7 2007/2008