8 Corrigé du DS du 11 janvier 2002
La durée de ce contrôle est de deux heures, tous les documents sont
autorisés (y compris ordinateurs).
Le barème probable est de 5 points pour les questions de cours, de
5 points pour les questions sur X11 et de 5 points pour chaque exercice
de codage.
8.1 Questions de cours sur les sockets
Répondez aux questions suivantes (deux lignes de réponse par question
suffisent) :
-
Citez une interface de programmation réseau qui ne soit pas
celle des sockets.
Principalement on peut citer Remote Procedure Call (RPC) de
SUN micro-systems mais il existe aussi Remote Method Invocation
(RMI) de java ou encore Transport Layer Interface (TLI) de l'OSI.
- Par quoi est définie une socket ?
Sa famille (exemple AF_INET), son mode (par exemple
SOCK_STREAM) et éventuellement le protocole utilisé
(dans l'exemple c'est forcement TCP).
- Donnez la taille en octets d'une adresse générique de socket.
Deux octets pour la famille et 14 de remplissage soit 16 octets.
- Existe-t-il des structures adresse de socket de taille inférieure
à celle de la structure adresse générique de socket ? En existe-t-il de
taille supérieure ?
Non, il n'existe pas de structure adresse de socket de taille
inférieure à 16 octets mais il en existe de taille supérieure
comme struct sockaddr_un.
- Sachant que addr est une variable de type
struct sockaddr_in, quel message le compilateur C va afficher en
analysant l'instruction bind(s,&addr,sizeof(addr)); ? Corrigez
l'instruction pour qu'elle se compile sans problème.
Le compilateur va générer un message d'avertissement au sujet du
typage de &addr. Le prototype de la fonction bind
impose un paramètre de type struct sockaddr * et la variable
utilisée est de type struct sockaddr_in *. L'instruction
correcte est bind(s,(struct sockaddr *)&addr,sizeof(addr));.
- Un descripteur de socket Internet en mode connecté est équivalent
à quelle autre entité système ? Est-ce encore vrai pour une socket Internet
en mode non connecté ?
Un descripteur de socket Internet en mode connecté est équivalent
à un descripteur de fichier. Ce n'est pas le cas en mode non
connecté car des données peuvent être supprimées du flux ou
dupliquées.
- Comment peut-on obtenir un pointeur de fichier à partir d'un
descripteur de socket ?
En utilisant la fonction fdopen.
- Quel est le détail important concernant l'initialisation du
troisième argument de la fonction accept ?
Le troisième argument d'accept doit pointer sur un entier
initialisé avec la taille de l'espace pointé par le second
argument. Cet espace est utilisé pour stocker l'adresse du client.
- Peut-on utiliser la fonction connect dans un client manipulant
des socketis Internet en mode non connecté ?
Oui, cela permet de recevoir des paquets UDP ne provenant que
d'une machine bien précise.
- Que symbolise la peluche que le redon a sorti de son sac en début
d'examen ? Un bonus supplémentaire pour ceux qui me donnent son nom.
Il s'agit de Tux, la mascotte du système d'exploitation Linux.
8.2 Questions sur le protocole X11
Répondez aux questions suivantes :
-
Donnez une ligne de commande pour afficher un serveur Xnest
de la machine choufleur sur le serveur X principal de la machine
courge. Attention, vous devez aussi donner la manipulation a effectuer
pour autoriser cet affichage.
Sur la machine courge il faut trouver la clef d'autorisation
d'affichage par la commande xauth list et il faut l'insérer
sur la machine choufleur par la commande xauth add.
Ensuite, sur la machine choufleur, il faut taper :
choufleur$ Xnest -display courge:0 :1
- Donnez les commandes à taper pour afficher un xeyes de la machine
concombre sur le serveur Xnest lancé à la question précédente.
On considère que le serveur Xnest accepte toute connection de client.
Sur la machine concombre il faut taper :
concombre$ xeyes -display choufleur:1
- On suppose que votre programme quémandeur de session XDM s'appelle
xdmquery. Son premier paramètre est le nom de machine sur laquelle
tourne le serveur de session et le second paramètre est le nom
complet du serveur X à prendre en charge (nom de la machine et numéro
d'écran). Utilisez ce programme pour que la machine rave prenne
en charge le serveur X principal de la machine concombre (il s'agit
du serveur concombre:0). Sur quelle machine la ligne de commande
doit être tapée ?
La ligne de commande peut être tapée sur toute machine disposant
de la commande xdmquery.
La commande à taper est :
$ xdmquery rave concombre:0
- Utilisez xdmquery pour que rave prenne en charge le
serveur Xnest lancé à la première question.
La ligne de commande peut être tapée sur toute machine disposant
de la commande xdmquery.
La commande à taper est :
$ xdmquery rave choufleur:1
- La ligne de commande de la question précédente provoque l'envoi de
paquets UDP. Quelles sont les machines qui émettent ces paquets UDP ?
Pouvez-vous dire sur quels ports ? Quelles sont les machines qui reçoivent
ces paquets ? Pouvez-vous dire sur quels ports ?
Les paquets UDP sont échangés entre la machine rave et la
machine sur laquelle est exécuté xdmquery. Cette dernière
machine émet ses paquets UDP à partir d'un port utilisateur choisi
par le système et reçoit les réponses de rave sur ce même
port. La machine rave reçoit des paquets sur le port
XDMCP (port 177) et émet ses réponses du même port.
- La ligne de commande des deux questions précédentes donne lieu
à des flux TCP. Expliquez ce que sont ces flux TCP et donnez les
caractéristiques des connexions TCP liées aux flux (c'est à dire
les adresses des sockets aux deux bouts de la connexion).
Attention n'oubliez pas qu'un serveur Xnest est à la fois un serveur
X et un client X.
Le premier flux TCP concerne la connexion d'un client X de la
machine rave sur le serveur Xnest de nom choufleur:1.
Il s'agit du client X d'indentification d'utilisateur lancé par le
serveur de sessions de rave.
Cette connexion TCP a pour origine rave d'un port utilisateur
vers le port 6001 de choufleur.
Le second flux TCP concerne l'affichage du programme Xnest sur le
serveur X courge:0. Cette connexion TCP a pour origine choufleur d'un port utilisateur vers le port 6000 de courge.
8.3 Extraits de code du tutorat
8.3.1 Code générique
Écrivez une fonction sendPacket qui permet d'envoyer un paquet
XDMCP et d'attendre pendant quelques secondes une réponse (la fonction
attend la réponse mais ne la lit pas). La fonction prend en paramètres
le descripteur de la socket d'envoi, la structure d'adresse de socket
du serveur XDM et le tampon XDMCP. La fonction ne relance
pas le paquet si aucune réponse n'est reçue mais retourne -1
dans ce cas.
Le prototype de cette fonction est imposé :
int sendPacket(int ds, /* Socket locale */
struct sockaddr_in adresse, /* Socket du serveur */
XdmcpBufferPtr paquet /* Contient le paquet XDMCP */
);
Exemple de code convenable
int sendPacket(int ds, /* Socket locale */
struct sockaddr_in adresse, /* Socket du serveur */
XdmcpBufferPtr paquet /* Contient le paquet XDMCP */
){
fd_set lecture ; /* Ensemble de descripteurs en lecture */
struct timeval minuteur; /* Structure du minuteur */
/* Envoyer le datagramme XDMCP */
sendto(ds,paquet->data,paquet->pointer,0,
(struct sockaddr *)&adresse,sizeof adresse);
/* Attente d'une reponse avec armement d'un minuteur */
FD_ZERO(&lecture); FD_SET(ds,&lecture);
minuteur.tv_sec=MINUTEUR_DUREE; minuteur.tv_usec=0;
select(ds+1,&lecture,NULL,NULL,&minuteur);
/* Calcul du code de sortie */
if(FD_ISSET(ds,&lecture)) return 0; else return -1;
}
8.3.2 Code spécifique
Écrivez la fonction remplissant une structure XdmcpBuffer avec un
paquet XDMCP de type QUERY. Le prototype de cette fonction est
imposé :
XdmcpBufferPtr buildQuery(void);
Vous utiliserez obligatoirement la fonction XdmcpWriteARRAYofARRAY8.
Exemple de code convenable
XdmcpBufferPtr buildQuery(void){
XdmcpBufferPtr buffer;
XdmcpHeader header;
ARRAYofARRAY8 array;
/* Allocation du tampon XDMCP */
buffer=allocXDMCPBuffer();
/* Ecriture de l'entete XDMCP */
header.version=XDM_PROTOCOL_VERSION;
header.opcode=(CARD16)QUERY;
header.length=1;
XdmcpWriteHeader(buffer,&header);
/* Ecriture des champs additionnels */
array.length=0;
array.data=NULL;
XdmcpWriteARRAYofARRAY8(buffer,&array);
return buffer;
}
Écrivez la fonction affichant une structure ARRAY8 sous forme
de chaîne de caractères (fonction pouvant être utilisée pour le
décodage des paquets WILLING par exemple).
Le prototype de cette fonction est imposé :
void displayString(ARRAY8 array);
Exemple de code convenable
void displayString(ARRAY8 array){
int i;
for(i=0;i<array.length;i++) printf("%c",array.data[i]);
printf("\n");
}