TP Noté « transfert de fichiers »

Vous allez réaliser différents clients et serveurs basés sur les travaux pratiques précédents sur le thème du transfert de fichiers.

Vous devez créer un nouveau projet dans votre environnement Eclipse que vous appellerez tpnote-VotreNom. Créez un fichier readme.txt dans lequel vous mettrez vos notes à destination des correcteurs.

Le barème est donné à titre d'indication.

Les questions 1 et 2 sont relativement indépendantes. Les questions 2 et 3 sont indépendantes, même s'il est plus facile de faire la question 3 à partir de la question 2 qui fonctionne. La question 4 n'est réalisable que si vous avez une question 2 ou 3 opérationnelle.

En fin de TP :

  1. si nécessaire, vous créerez un fichier readme.txt dans lequel vous mettez vos notes à destination des correcteurs ;
  2. vous exporterez ce projet sous la forme d'une archive :
  3. télé-chargez le fichier sur moodle afin de fournir le résultat de votre travail ;
  4. vérifiez avec l'enseignant présent dans la salle que le fichier téléchargé est correct.

Ce TP est réalisé en plusieurs étapes. Pour chacune, vous devez créer un paquetage portant le nom de l'étape.

1. Envoi d'un fichier par un client (barème indicatif 5 pts)

Dans cette étape, un client envoie un fichier à un serveur.

Pour cette étape, vous devez créer dans le paquetage fileClientSenderSingle un client et un serveur qui utilisent directement des ByteBuffers.

1.1. Partie client (barème indicatif, 2,5 pts)

Le client est appelé de la manière suivante :

java EnvoiSimpleClient machine port nomfichier

Vous devez choisir comment envoyer le nom et la taille du fichier, puis l'ensemble du contenu du fichier.

Voici quelques lignes vous permettant de lire le contenu d'un fichier :

  File file;
  FileInputStream fis;
  FileChannel fc;
  ByteBuffer readBuf;
  file = new File(argv[2]);
  fis = new FileInputStream(file);
  fc = fis.getChannel();
  totalSize = file.length();
  readBuf = ByteBuffer.allocate(4096);
  int readSize = 0;
  totalSize = 0L;
  do {
    // lecture d'un bloc du fichier original
    readSize = fc.read(readBuf);
    if (readSize > 0) {
      totalSize += readSize;
      // TODO: placez ici le code qui gère le contenu du fichier
      readBuf.clear();
    }
  } while (readSize > 0);

1.2. Partie serveur (barème indicatif, 2,5 pts)

Le serveur se met en attente de connexion sur un port. Il respecte les choix que vous avez fait pour envoyer le nom, la taille, puis les données.

Le serveur peut successivement recevoir plusieurs fichiers. Il doit donc boucler sur l'attente d'une requête de connexion puis la réception du fichier correspondant.

Lorsque le serveur reçoit le nom du fichier, il crée un fichier qui porte ce nom plus l'extension .copy pour éviter d'écraser le fichier d'origine lorsque le client et le serveur sont exécutés sur la même machine.

La création d'un fichier s'effectue de la manière suivante :
  FileChannel fc;
  FileOutputStream fos = new FileOutputStream(fileName + ".copy");
  fc = fos.getChannel();
L'écriture d'un ByteBuffer via un FileChannel se réalise avec la méthode write(ByteBuffer).

2. Sérialisation des données transmises (barème indicatif, 5 pts)

Dans cette étape, le client envoie un fichier à un serveur.

Réalisez dans un paquetage appelé envoisimplemsg une version du protocole précédant réalisé avec trois types de messages sérialisés :

  1. message de type 1 contenant le nom du fichier,
  2. message de type 2 contenant la taille du fichier, et
  3. message de type 3 contenant les blocs de données du fichier (taille max 4096 octets).

Vous pouvez utiliser la classe HalfDuplexMsgWorker que vous avez réalisée lors des TPS, ou celle qui correspond au lien suivant: HalfDuplexMsgWorker.java.

Vous aurez aussi besoin de l'énumération permettant de gérer de manière plus lisible l'état de réception d'un message ReadMessageStatus.java.

Vous pouvez aussi avoir besoin d'une classe d'exception pour préciser qu'une séquence de messages n'est pas respectée MessageSequenceException.java.

3. Retournement du protocole (barème indicatif, 5 pts)

Dans cette étape, c'est le serveur qui envoie le fichier dont le client donne le nom.

Réalisez dans un paquetage appelé receptionsimplemsg un protocole permettant au client de recevoir un fichier dont il émet le nom.

Le protocole est alors le suivant :

  1. envoi d'un message de type 1 contenant le nom du fichier désiré ;
  2. réception d'un message de type 2 contenant la taille du fichier. Lorsque celle-ci est égale à -1, cela signifie que le fichier ne peut pas être envoyé par le serveur ;
  3. puis réception des messages de type 3 contenant les blocs de données en provenance du serveur.

4. Serveur multiclient (barème indicatif, 5 pts)

Dans cette étape, le transfert de fichier est effectué, selon votre choix, soit du client vers le serveur comme dans la question 2, soit du serveur vers le client comme dans la question 3. La nouveauté de cette étape est que le serveur accepte plusieurs transferts simultanés en provenance de ou vers plusieurs clients.

Afin de rendre les interactions entre le serveur et les clients moins synchrones. Réalisez dans un paquetage appelé serveurmultiasynchrone le serveur d'une des deux étapes précédentes, donc soit un serveur qui reçoit des fichiers de plusieurs clients, soit un serveur qui envoie des fichiers à plusieurs clients.

Le serveur doit pouvoir accepter plusieurs demandes de connexion de clients simultanément, et il doit pouvoir envoyer ou recevoir, selon votre choix, les données de plusieurs fichiers en parallèle.