Issuu on Google+

DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

} catch (Exception Ex) { gestion_Erreur(Ex); } } Ce bouton sert à rompre le flux et à le réinitialiser en cas de problème de connexion. Il ne reste plus qu‛à créer la procédure tri_date() comme suit: private void tri_date(ListView liste) { System.Collections.ArrayList tableau = new System.Collections.ArrayList(); for (int i =0; i<liste.Items.Count; i++) { tableau.Add(liste.Items[i].SubItems[2].Text + «|» + liste.Items[i]. SubItems[1].Text + «|» + liste.Items[i].Text + «|» + liste.Items[i].SubItems[3].Text); } tableau.Sort(); liste.Items.Clear(); for(int i = 0; i<tableau.Count; i++) { int position1 = tableau[i].ToString().IndexOf(«|»,0); int position2 = tableau[i].ToString().IndexOf(«|»,position1 + 1); int position3 = tableau[i].ToString().IndexOf(«|»,position2 + 1); string el1 =tableau[i].ToString().Substring(position2 + 1, position3 - position2 -1); string el2 =tableau[i].ToString().Substring(position1 + 1, position2 - position1 -1); string el3 =tableau[i].ToString().Substring(0, position1); string el4 =tableau[i].ToString().Substring(position3 + 1); construit_liste(liste, el1, el2, el3, el4); } }

Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 22


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe COMMUNICATION RÉSEAU - PIÈCE JOINTE Ici je reprends l‛application précédente, Client_et_serveur dans laquelle j‛explique comment une console peut être à la fois client et serveur et comment elle communique avec tous les utilisateurs du réseau. Dans cette section, je lui ajoute quelques fonctionnalités supplémentaires dont une de taille, l‛envoi de pièces jointes, quelque soit la taille du fichier. Chaque fichier est lu à l‛aide de la classe BinaryReader et découpé en petits tableaux de 2048 octets. Le destinataire, dans le Thread d‛écoute, réceptionne tous ces petits paquets, les assemble et reconstruit le fichier à l‛aide de la classe BinaryWriter cette fois.

MODIFICATIONS

DU FORMULAIRE

● Double cliquer sur le fichier client_et_ serveur.sln situé dans le sous dossier Sources pour démarrer la solution à modifier, ● Afficher le formulaire en mode Design, L‛onglet Boîte d‛envoi doit être actif. Je commence par ajouter quelques contrôles nécessaires.

La capture ci-dessus illustre le formulaire tel que je le récupère. Ci-contre, je présente le résultat à atteindre. ● Ajouter deux boutons comme l’illustre la capture, ● Les nommer respectivement joindre et rompre, ● Modifier de la même façon leur texte, ● Régler éventuellement leur propriété Anchor, comme le premier bouton de façon à respecter le redimensionnement, Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 1


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

● Ajouter ensuite un GroupBox en bas à droite, ● Le nommer groupe5 et changer son texte en Pièce jointe, ● Régler sa propriété Anchor sur Bottom, Left, Right, ● Ajouter un contrôle Label à l’intérieur de ce GroupBox, ● Le renommer piece et supprimer son texte. Voilà pour l‛onglet Boîte de réception. Le bouton joindre doit permettre de désigner un fichier à envoyer avec le message. Le bouton rompre doit permettre de casser le flux de communication en cas de souci. La zone piece affichera le nom de la pièce jointe. ● Ajouter ensuite un contrôle ProgressBar en dehors des onglets sur la partie basse du formulaire, Il faudra sans doute étirer le formulaire. ● Le renommer progression, J‛utilise ce contrôle ProgressBar pour renseigner en temps réel sur l‛état d‛avancement du transfert de la pièce jointe. Comme je l‛ai dit précédemment, le bouton joindre sert à sélectionner un fichier à joindre. J‛utilise donc pour ce faire une boîte de dialogue commune, OpenFileDialog. ● Ajouter un contrôle OpenFileDialog, ● Le renommer ouvrir, ● Sélectionner maintenant le deuxième onglet, Boîte de réception,

Comme l‛illustre ces copies d‛écran, j‛ajoute donc deux boutons ainsi qu‛un Label dans un GroupBox.

Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 2


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

● Ajouter un premier bouton en bas à gauche de l’onglet et le nommer supp_r, ● Ajouter un second bouton et le nommer po, ● Régler la propriété Anchor de chacun des boutons sur Bottom, Left, Ainsi, ils restent ancrés en bas à gauche. Pour les images, c‛est à votre guise. ● Ajouter ensuite un contrôle GroupBox et le nommer groupe6, ● Insérer un Label dans ce GroupBox et le nommer piecer, ● Régler leur propriété Anchor sur Left, Right, J‛utilise le premier bouton pour supprimer le message sélectionné. Le deuxième bouton me sert à ouvrir la pièce jointe au message sélectionné. Le Label quant à lui sert à rappeler le nom du fichier de la pièce jointe. ● Sélectionner maintenant le troisième onglet, Eléments envoyés,

Comme précédemment, j‛ajoute deux boutons et un Label, pour les mêmes raisons.

● Insérer un Label dans ce GroupBox et le nommer piecee, ● Régler leur propriété Anchor sur Left, Right,

● Ajouter un premier bouton en bas à gauche de l’onglet et le nommer supp_e, ● Ajouter un second bouton et le nommer pe, ● Régler la propriété Anchor de chacun des boutons sur Bottom, Left, ● Ajouter ensuite un contrôle GroupBox et le nommer groupe7,

Voilà, tout est prêt ou presque. On va donc maintenant ajouter le code au précédent sachant que l‛application telle qu‛on la récupère, sait déjà communiquer à travers le réseau par le biais de messages. Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 3


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

MODIFICATION

DU CODE

● Ajouter la référence à l’espace de noms IO pour commencer, //E/S gestion des fichiers et dossiers...Fichiers ici... using System.IO; J‛utilise cet espace de noms pour lire les informations binaires des pièces jointes et les réécrire dès réception. ● Ajouter ensuite les quelques déclarations publiques suivantes: //============================ //Chemin de l’application... //============================ string chemin; //Savoir s’il y a un fichier joint après le message... bool la_fin = false; string laPieceJ = «»; string laTailleR = «»; long taille_conv = 0; long compteur = 0; J‛utilise la variable chemin pour faire référence au dossier de l‛exécutable de l‛application. La variable booléenne la_fin est un test que j‛utilise lors de l‛écoute pour savoir si, suite au message il s‛agit bien de la fin de la transmission car dans le cas des pièces jointes, je dois rester à l‛écoute pour les réceptionner et rompre le flux seulement après. Les variables de type string laPieceJ et laTailleR servent respectivement à mémoriser le nom de la pièce jointe et la taille en Octets mais convertie en string de cette dernière. Il s‛agit d‛informations que j‛envoie concaténées au message. La variable taille_conv mémorise la taille du fichier joint mais en numérique cette fois. Enfin, j‛utilise la variable compteur dans la boucle de réception de la pièce jointe pour savoir si l‛intégralité du fichier est reçu et, auquel cas si je peux rompre le flux pour rendre la console de nouveau disponible pour d‛autres connexions. L‛initialisation des composants quant à elle ne change pas. Je récupère l‛adresse IP de la machine et lance instantanément le Thread d‛écoute. Le Thread d‛écoute, en revanche, est largement remanié pour être capable de réceptionner les pièces jointes, s‛il y en a !! Je commence par la boucle while(arretS). C‛est ici que je réceptionne le message et que je scrute pour savoir s‛il est accompagné d‛une pièce jointe. Juste après la réception et le décodage du message, je déclare une variable idx_joint pour mémoriser l‛emplacement d‛un TAG signifiant qu‛une pièce jointe va suivre. C‛est ainsi que le message devra être envoyé. Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 4


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

● Ajouter la ligne de code suivante: //On traduit les bytes en caractères en default (pour les accents) string donnees = Encoding.Default.GetString(transfert); //Le message est accompagné d’un fichier joint ? int idx_Joint = donnees.IndexOf(«|FICHIER|»,0); ● Supprimer ensuite l’intégralité de l’instruction if qui suit (if (donnees.Substring(0,1)!=»D»)), ● Et la remplacer par la suivante: if(idx_Joint != -1) { int idx_laTaille = donnees.IndexOf(«|TAILLE|»,0); laPieceJ = donnees.Substring(idx_Joint + 9, idx_laTaille-1 - idx_Joint 8); //+8: longueur du TAG |TAILLE| laTailleR = donnees.Substring(idx_laTaille + 8, donnees.IndexOf(«|», idx_ laTaille + 8) - idx_laTaille - 8); taille_conv = Convert.ToInt32(laTailleR); la_fin =false; } else { la_fin = true; } Si le tag |FICHIER| est trouvé, cela signifie que l‛expéditeur indique que le message est suivi d‛une pièce jointe et que je dois donc la réceptionner. L‛expéditeur envoie toutes les autres informations nécessaires au traitement de cette pièce, sous forme de tag, ce que cette instruction if s‛efforce de traiter et récupérer. Ainsi, je mémorise dans la variable idx_laTaille, la position du tag |TAILLE| de façon à réceptionner la taille du fichier joint sous forme de string dans un premier temps, à l‛aide de la variable laTailleR qui suit. Je converti ensuite cette valeur en entier dans la variable taille_conv. Cette dernière servira de borne supérieure à la boucle de réception de la pièce jointe. Puis je règle le booléen la_fin à false puisqu‛en effet, après réception du message, l‛écoute ne doit pas se clore, la pièce jointe suit. Dans le cas contraire, le tag |FICHIER| n‛étant pas trouvé, le même booléen est réglé à true pour que l‛écoute se termine et se réinitialise dès que la réception du message est achevée. ● Supprimer ensuite les lignes de code suivantes: int debut = 3; int fin = donnees.IndexOf(«:»,0); string de = donnees.Substring(debut, fin - 1); string sujet = donnees.Substring(fin + 1); construit_liste(m_r,de,sujet,System.DateTime.Now.ToString()); this.WindowState=FormWindowState.Normal; Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 5


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

Ces lignes permettaient de traiter et récupérer le message lorsqu‛il n‛était pas accompagné d‛une pièce jointe. ● Commencer par saisir l’instruction if suivante, à la place: //Procédure stockant les informations reçus sur le d.dur dans le dossier //local recus... if (donnees.Substring(0,1) == «D») { stocke_infosr(donnees, laPieceJ); compteur = 0; if (la_fin == true) { if(onglets.SelectedIndex==1) { //Remplit la liste des messages reçus... m_r.Items.Clear(); string ledossierr = chemin + «recus\\»; //Récupère les infos sur le répertoire passé en argument DirectoryInfo repr = new DirectoryInfo(ledossierr); //Récupère les fichiers du répertoire FileInfo[] lesFichiersr = repr.GetFiles(); foreach(FileInfo leFichier in lesFichiersr) { if(leFichier.Name.Substring(leFichier.Name.Length-6)==»de.txt») { avt_ContruitListe(m_r, ledossierr + leFichier.Name); } } } jecoute.Stop(); module_Serveur.Abort(); module_Serveur = new Thread(new ThreadStart(Ecoute)); module_Serveur.Start(); } } Le premier if teste s‛il s‛agit du message ou de la pièce jointe. Si les données reçues et décodées commencent par un ‘D‛ (C‛est comme ça que le client envoie le message), alors j‛appelle la procédure stocke_infosr() en lui passant le contenu du message. Je créerai cette procédure ensuite. Son but sera de stocker sur le disque les informations du message (Destinataire, date, contenu...). Si le booléen la_fin est à true, aucune pièce jointe ne suivra. Donc, dans le cas où l‛onglet de la boîte de réception est actif (if(onglets.SelectedIndex==1)), je reconstruis la liste des messages et raffraichis le ListView de façon à ce que le nouveau message s‛affiche en temps réel. Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 6


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

Je commence par supprimer toutes les informations comprises dans le ListView (m_r.Items. Clear();). J‛instancie ensuite un objet DirectoryInfo pour récupérer les informations sur le dossier contenant tous les messages stockés (DirectoryInfo repr = new DirectoryInfo(ledossierr);) . Puis je stocke dans un objet FileInfo tous les fichiers contenus dans ce dossier, grâce à la méthode GetFiles() de l‛objet DirectoryInfo. La boucle foreach qui suit passe logiquement en revue tous les fichiers compris dans ce dossier. Si les six dernières lettres du nom de fichier correspondent à ‘de.txt‘ (Ceci indique qu‛il s‛agit du fichier destinataire), j‛appelle la procédure avt_ContruitListe, à laquelle je passe le ListView à traiter ainsi que le nom de fichier du message. Je créerai cette procédure plus tard. Son but sera de récupérer toutes les informations dispatchées du message couramment traité. Maintenant, je m‛occupe du cas contraire (else), c‛est à dire lorsque les données reçues ne correspondent pas au message mais à la pièce jointe. Il s‛agit d‛une partie volumineuse du code, mais c‛est aussi la plus importante. En outre, c‛est grâce à elle que n‛importe qu‛elle pièce jointe, quelle que soit sa taille, peut être transmise et reçue. ● Ajouter la branche else à la suite du if, else { while(compteur<=taille_conv) { FileStream graveur = new FileStream(chemin laPieceJ,FileMode.OpenOrCreate, FileAccess.ReadWrite); BinaryWriter ecrire = new BinaryWriter(graveur);

+

«recus\\»

ecrire.Seek(0,SeekOrigin.End); ecrire.Write(transfert,0,transfert.Length); ecrire.Close(); graveur.Close(); compteur += 2048; //Pour que la réception et acquisition s’enchaînent... monSocket.Receive(transfert); } if(onglets.SelectedIndex==1) { m_r.Items.Clear(); string ledossierr = chemin + «recus\\»; DirectoryInfo repr = new DirectoryInfo(ledossierr); FileInfo[] lesFichiersr = repr.GetFiles(); (...==> SUITE)

Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 7

+


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

foreach(FileInfo leFichier in lesFichiersr) { if(leFichier.Name.Substring(leFichier.Name.Length-6)==»de.txt») { avt_ContruitListe(m_r, ledossierr + leFichier.Name); } } } Tout d‛abord, et le point le plus important réside là, j‛entame une boucle de réception de la pièce jointe qui ne se termine que lorsque le nombre d‛octets récupérés correspond à la taille de fichier transmise dans les informations du message (while(compteur<=taille_conv)). Les données aussitôt transmises et aussitôt reçues sont instantanément traitées pour ne pas risquer de saturer la mémoire tampon de transfert (BufferSize) ce qui aurait pour effet de bloquer le Socket d‛écoute. Par le biais des classes FileStream et BinaryWriter, je crée mon objet ecrire qui me permet de reconstituer instantanément le fichier selon les paquets (2048 octets) de données reçues via le flux de communication. Je me positionne tout d‛abord à la fin du fichier, à l‛aide de la méthode Seek (ecrire.Seek(0,SeekOrigin.End);) pour poursuivre l‛écriture et ne pas écraser ce qui a déjà été écrit. Puis, j‛écris ces données à l‛aide de la méthode Write de la classe BinaryWriter. Ici les données ne sont pas décodées puisque je reconstitue le code binaire du fichier. Bien sûr, je ferme instantanément les objets FileStream et BinaryWriter avant de les rouvrir au prochain passage dans la boucle (réception d‛un nouveau paquet) pour poursuivre l‛écriture là où je l‛ai laissée. J‛incrémente le compteur du nombre d‛octets écrits (compteur += 2048;). Je force la réception de données à l‛aide de la méthode Receive de l‛objet Socket (monSocket. Receive(transfert);). Et puis, comme précédemment, dans le cas du message seul, j‛amorce la procédure permettant de reconstruire la liste des messages et de rafraîchir le ListView en conséquence. La fin du code ne change pas. Je ferme l‛écoute pour la réinitialiser aussitôt afin de rompre le flux avec ce client et de rester disponible pour toutes les demandes de connexion à venir. jecoute.Stop(); module_Serveur.Abort(); module_Serveur = new Thread(new ThreadStart(Ecoute)); module_Serveur.Start(); la_fin = true; } } } catch { ... Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 8


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

Je crée ensuite la procédure stocke_infosr(), appelée par le Thread d‛écoute et dont l‛objectif est de stocker sur le disque dur, dans le dossier local recus, toutes les informations attachées à un message comme la date de réception, le contenu... ● Saisir le code de cette procédure comme indiqué ci-dessous: private void stocke_infosr(string donnees, string pieceJ) { int debut = 3; int fin = donnees.IndexOf(«:»,0); int idx_Joint = donnees.IndexOf(«|FICHIER|»,0); string de = donnees.Substring(debut, fin - 3); string sujet=»»; string laPieceJ = pieceJ; if(idx_Joint == -1) { sujet = donnees.Substring(fin + 1); } else { sujet = donnees.Substring(fin + 1,idx_Joint - fin - 1); } string heure = System.DateTime.Now.Hour.ToString() + «h» + System.DateTime. Now.Minute.ToString() + «mn» + System.DateTime.Now.Second.ToString() + «s»; StreamWriter ecrire = new StreamWriter(chemin + «recus\\» + de + «-» + heure + «-de.txt»); ecrire.WriteLine(de); ecrire.Close(); ecrire = new StreamWriter(chemin + «recus\\» + de + «-» + heure + «su.txt»); ecrire.WriteLine(sujet); ecrire.Close(); ecrire = new StreamWriter(chemin + «recus\\» + de + «-» + heure + «da.txt»); ecrire.WriteLine(System.DateTime.Now.ToString()); ecrire.Close(); ecrire = new StreamWriter(chemin + «recus\\» + de + «-» + heure + «pi.txt»); ecrire.WriteLine(laPieceJ); Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 9


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

ecrire.Close(); } Je commence par mémoriser la présence du symboles ‘:‘ dans le message car le nom de l‛expéditeur se termine par les deux points (int fin = donnees.IndexOf(«:»,0);). Dans le cas de la présence éventuelle d‛une pièce jointe, je mémorise la présence du tag |FICHIER| (int idx_Joint = donnees.IndexOf(«|FICHIER|»,0);). J‛extrais le nom de l‛expéditeur (string de = donnees.Substring(debut, fin - 3);). Je récupère la pièce jointe passée en paramètres (string laPieceJ = pieceJ;). Selon la valeur de la variable idx_Joint, je sais si après l‛expéditeur, le message est seul ou s‛il est encore suivi d‛autres informations. J‛extrais donc le sujet en conséquence à l‛aide de cette instruction if: if(idx_Joint == -1) { sujet = donnees.Substring(fin + 1); } else { sujet = donnees.Substring(fin + 1,idx_Joint - fin - 1); } Je construis l‛heure de réception sous forme de string: string heure = System.DateTime.Now.Hour.ToString() + «h» + System.DateTime. Now.Minute.ToString() + «mn» + System.DateTime.Now.Second.ToString() + «s»; Et maintenant que je dispose des informations attachées au message, je les enregistre chacune dans des fichiers texte indépendants à l‛aide de la classe StreamWriter que j‛instancie pour exploiter un objet que je nomme ecrire. Tous ces fichiers portent le même nom (expéditeur, suivi de la date...); seul un suffixe de deux lettres change pour les différencier. Ainsi le fichier au suffixe de stocke le nom de l‛expéditeur. Le fichier au suffixe su stocke le contenu du message. Celui au suffixe da stocke la date et l‛heure. Et enfin, celui au suffixe pi stocke de nom de fichier de la pièce jointe. Quant à la pièce jointe elle même, elle est enregistrée instantanément sur le disque dur pendant le Tread d‛écoute comme nous l‛avons vu précédemment. Ensuite, je modifie quelque peu la procédure construit_Liste() de façon à ajouter un nouvel élément dans une quatrième colonne masquée pour mémoriser l‛emplacement et le nom du fichier correspondant au message sur le disque dur. ● Modifier cette procédure en ajoutant les lignes représentées en gras comme suit (Ne pas oublier d’ajouter la déclaration de ce quatrième élément dans les paramètres de la procédure):

Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 10


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

private void construit_liste(ListView Liste, string el1, string el2, string el3, string el4) { ListViewItem elmt; ListViewItem.ListViewSubItem ssElmt; //Crée l’élément principal elmt = new ListViewItem(); elmt.Text = el1; //Crée les 2 Ss éléments ssElmt = new ListViewItem.ListViewSubItem(); ssElmt.Text = el2; elmt.SubItems.Add(ssElmt); // Ajoute à la collection ssElmt = new ListViewItem.ListViewSubItem(); ssElmt.Text = el3; elmt.SubItems.Add(ssElmt); // Ajoute à la collection ssElmt = new ListViewItem.ListViewSubItem(); ssElmt.Text = el4; elmt.SubItems.Add(ssElmt); // Ajoute à la collection Liste.Items.Add(elmt); Liste.Refresh(); } ● Au chargement du formulaire, ajouter l’affectation de la variable publique chemin pour mémoriser le chemin local de l’application: private void com_reseau_Load(object sender, System.EventArgs e) { //Chemin de l’application... chemin = Application.StartupPath; if(chemin.Substring(chemin.Length - 1,1) != «\\») chemin += «\\»; //Ajout d’utilisateurs du réseau... liste_r.Items.Add(«Stef»); liste_r.Items.Add(«localhost»); liste_r.Items.Add(«adminchrisian»); liste_r.Items.Add(«portabledp»); liste_r.Items.Add(«pascal»); liste_r.SelectedIndex = 0; etat.Panels[1].Text = adresse_Ip.ToString(); etat.Panels[2].Text = nom_Machine; }

Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 11


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

Ensuite, au clic sur le bouton Envoyer, je dois stocker toutes les informations du message que j‛envoie (Date, contenu, pièce jointe...) et envoyer le message en récupérant les données binaires du fichier joint (Si fichier joint il y a) et les envoyer par le flux du réseau. ● Modifier la procédure envoyer_Click() comme suit: private void envoyer_Click(object sender, System.EventArgs e) { stocke_info(); envoie_Serveur(); } J‛ajoute donc l‛appel à la procédure stocke_info() qui comme son homologue stocke_infosr() se charge de stocker les informations relatives aux messages, sur le disque dur. Mais cette fois-ci, il s‛agit des messages envoyés et non reçus. Je crée cette procédure par la suite. De plus, je modifie l‛appel à la procédure envoie_Serveur() qui ne requiert plus de paramètre. Je m‛occuperai de cette dernière ensuite. ● Créer la procédure stocke_info() comme suit: private void stocke_info() { if(piece.Text != «») { FileInfo fichier = new FileInfo(piece.Tag.ToString()); //Réalise une copie du fichier joint dans le rep local ‘envoyes’... fichier.CopyTo(chemin + «envoyes\\» + piece.Text, true); } string heure = System.DateTime.Now.Hour.ToString() + «h» + System.DateTime. Now.Minute.ToString() + «mn» + System.DateTime.Now.Second.ToString() + «s»; StreamWriter ecrire = new StreamWriter(chemin + «envoyes\\» + nom_Machine + « (« + adresse_Ip.ToString() + «)-» + heure + «-de.txt»); ecrire.WriteLine(nom_Machine + « (« + adresse_Ip.ToString() + «)»); ecrire.Close(); ecrire = new StreamWriter(chemin + «envoyes\\» + nom_Machine + « (« + adresse_Ip.ToString() + «)-» + heure + «-su.txt»); ecrire.WriteLine(m.Text); ecrire.Close(); ecrire = new StreamWriter(chemin + «envoyes\\» + nom_Machine + « (« + adresse_Ip.ToString() + «)-» + heure + «-da.txt»); ecrire.WriteLine(System.DateTime.Now.ToString()); ecrire.Close(); ecrire = new StreamWriter(chemin + «envoyes\\» + nom_Machine + « (« + adresse_Ip.ToString() + «)-» + heure + «-pi.txt»); Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 12


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

ecrire.WriteLine(piece.Text); ecrire.Close(); } S‛il y a une pièce jointe (if(piece.Text != «»)), j‛utilise la méthode CopyTo de la classe FileInfo pour réaliser une copie locale (sous dossier envoyes) de cette dernière. Pour le reste, je ne fournis pas plus d‛explication puisque cette procédure agit exactement de la même façon que stocke_infosr(). Je m‛attarde maintenant sur la procédure envoie_Serveur() qui subit de larges modifications puisqu‛elle permet de découper en petits paquets de 2048 Octets les pièces jointes et d‛envoyer ces paquets à travers le flux du réseau. ● Commencer par supprimer la déclaration de variable en paramètre de la procédure (envoie_Serveur()), ● Juste avant la déclaration de la variable NetworkStream, ajouter la déclaration de la variable message, leClient.Connect(choix, port); etat.Text = «Connexion en cours...»; string message = m.Text; //================================================================== //La transmission de données se fait via un objet NetworkStream qui //s’obtient en utilisant la méthode GetStream...System.Net.Sockets //================================================================== NetworkStream transmission = leClient.GetStream(); Cette dernière mémorise simplement le contenu du message. ● Supprimer ensuite les six lignes (Listées ci-dessous) de codes qui suivent, jusqu’à transmission.Close(): message = «De « + nom_Machine + « (« + adresse_Ip.ToString() + «): « + message; Byte[] envoie = System.Text.Encoding.Default.GetBytes(message.ToCharArray()); transmission.Write(envoie,0,envoie.Length); string de = nom_Machine + « (« + adresse_Ip.ToString() + «): «; string sujet = m.Text; construit_liste(m_e,de, sujet, System.DateTime.Now.ToString()); ● Ajouter à la place la déclaration de la variable taille: long taille = 0; J‛utiliserai cette dernière pour mémoriser la taille du fichier joint.

Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 13


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

● Ajouter ensuite l’instruction if suivante (toujours avant le transmission.Close()): if(piece.Text == «») { message = «De « + nom_Machine + « (« + adresse_Ip.ToString() + «): « + message; long taille_affine = message.Length; Byte[] envoie = new Byte[taille_affine]; envoie = System.Text.Encoding.Default.GetBytes(message.ToCharArray()); transmission.Write(envoie,0,envoie.Length); } S‛il n‛y a pas de pièce jointe, je me contente de construire le message avec premièrement l‛expéditeur suivi de ‘:‛ puis le message lui même. J‛encode ce message dans un tableau de Bytes et je l‛envoie à travers le flux réseau (par le port sélectionné et en direction du destinataire choisi précédemment: leClient.Connect(choix, port);). Dans le cas contraire, je choisis de construire le message avec des TAGS indiquant le nom et la taille de la pièce jointe qui suivra. C‛est ainsi que le serveur saura si après réception du message il devra stopper l‛écoute ou au contraire la poursuivre pour réceptionner la pièce. ● Donc, ajouter la branche else qui suit: else { FileInfo Lecteur = new FileInfo(chemin + «envoyes\\» + piece.Text); taille = Lecteur.Length; message = «De « + nom_Machine + « (« + adresse_Ip.ToString() + «): « + message + «|FICHIER|» + piece.Text + «|TAILLE|» + taille.ToString() + «|»; Byte[] envoie ray());

=

System.Text.Encoding.Default.GetBytes(message.ToCharAr-

transmission.Write(envoie,0,envoie.Length); } Je commence par récupérer la taille (en Octets) de la pièce jointe précédemment copiée dans le dossier local envoyes, à l‛aide de la variable taille et d‛un objet FileInfo. J‛insère dans le message, après les tags, les informations nécessaires à la réception (comme le nom du fichier: piece.Text et la taille du fichier: taille.ToString()). Et puis de nouveau, j‛encode le message dans un tableau de Bytes et le transmets au destinataire via le flux à l‛aide de l‛objet NetworkStream (transmission). Ensuite, si pièce jointe il y a, je dois envoyer ce fichier quel que soit sa taille. Je dois donc construire une boucle chargeant à chaque passage un tableau de Bytes pour le transfert jusqu‛à ce que la taille finale du fichier soit atteinte. Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 14


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

● A la suite, ajouter donc ce code: if(piece.Text != «») { Temporise(); FileStream Lecteur = new FileStream(chemin + «envoyes\\» + piece.Text,FileMode. Open, FileAccess.Read); BinaryReader Lire = new BinaryReader(Lecteur); progression.Maximum = Convert.ToInt32(Lecteur.Length); while(Lecteur.Position<Lecteur.Length) { byte[] tableau = new Byte[2048]; progression.Value=Convert.ToInt32(Lecteur.Position); //Lire. tableau = Lire.ReadBytes(2048); transmission.Write(tableau,0, tableau.Length); etat.Panels[0].Text=»Envoyés: « + Lecteur.Position.ToString() + « sur « + Lecteur.Length.ToString(); } etat.Panels[0].Text = «Envoi terminé !»; piece.Text = «»; Lire.Close(); Lecteur.Close(); } Tout d‛abord j‛appelle la procédure Temporise() que je créerai ensuite. Comme son nom l‛indique, cette dernière sert à laisser s‛écouler quelques instants (infimes) pour s‛assurer que le message part bien tout seul et que peut alors commencer le transfert des informations de la pièce jointe. Sans cette temporisation, les informations du message et de la pièce jointe se mélangent. Ensuite, je crée un objet BinaryReader (Lire) pour récupérer les informations binaires de la pièce à transférer. J‛initialise la capacité maximum de la barre de progression à la taille du fichier pour suivre l‛avancement du transfert. Puis, je commence la boucle de transmission (while(Lecteur. Position<Lecteur.Length)). Grâce aux propriétés Position et Length de l‛objet BinaryReader je suis en mesure d‛indiquer que cette boucle ne se termine que lorsque la position dans le flux du fichier est équivalente à la fin du fichier. Je déclare ensuite un petit tableau de Bytes pour le transport (byte[] tableau = new Byte[2048];). Je charge ce tableau des données binaires du fichier jusqu‛à sa capacité max (tableau = Lire. ReadBytes(2048);). Et comme toujours, la méthode Write de l‛objet NetworkStream (transmission) me permet d‛envoyer ce paquet via le réseau au destinataire. Je ferme la boucle et, puisque la transmission est terminée, je ferme les objets BinaryReader et FileStream à l‛aide de leur Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 15


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

méthode Close(). Il ne reste plus qu‛à fermer le if, rompre le flux (transmission.Close();) et fermer le client (leClient.Close();), pour signifier au serveur qu‛il peut terminer l‛écoute pour la réinitialiser. ● Créer ensuite la procédure Temporise(), énoncée plus haut, comme suit: private void Temporise() { double debut = Convert.ToDouble(System.DateTime.Now.Second); while (Convert.ToDouble(System.DateTime.Now.Second) < debut + 0.2) { Application.DoEvents(); } } Voilà, rien de bien compliqué. Je fais patienter le déroulement du code pendant 2 dixièmes de secondes à l‛aide d‛une boucle et surtout de la méthode DoEvents() (qui rend la main) de l‛objet Application. Maintenant je choisis de programmer le bouton joindre permettant de désigner le fichier à transmettre. ● Saisir le code de ce bouton comme suit: private void joindre_Click(object sender, System.EventArgs e) { try { if(ouvrir.ShowDialog()==DialogResult.OK) { //Instance FileInfo pour manipuler le fichier à joindre... //ouvrir.FileName ==> Chemin + nom du fichier... FileInfo fichier = new FileInfo(ouvrir.FileName); piece.Text = fichier.Name; //Nom du fichier seul... piece.Tag = fichier.FullName; //Avec chemin... } } catch (Exception Ex) { gestion_Erreur(Ex); } } J‛utilise tout d‛abord la boîte de dialogue commune OpenFileDialog (ouvrir). Si l‛utilisateur valide son choix par OK, j‛instancie un objet FileInfo (fichier) pour récupérer le nom du fichier et son chemin d‛accès. Je charge ces informations dans le Label piece. Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 16


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

Ensuite, lorsque l‛utilisateur change d‛onglet, je choisis de reconstruire les listes des messages pour les rafraîchir. ● Après avoir ajouter le gestionnaire d’événements correspondant, saisir le code correspondant au changement d’onglet, comme suit: private void onglets_SelectedIndexChanged(object sender, System.EventArgs e) { try { switch(onglets.SelectedIndex) { case 0: break; case 1: //Remplit la liste des messages reçus... m_r.Items.Clear(); string ledossierr = chemin + «recus\\»; //Appel de la procédure récupérant ts les fichiers de stockage des msg. scanne_fichier(m_r, ledossierr); //Procédure triant croissant sur la date... tri_date(m_r); break; case 2: //Remplit la liste des messages envoyés... m_e.Items.Clear(); string ledossier = chemin + «envoyes\\»; scanne_fichier(m_e, ledossier); //Procédure triant croissant sur la date... tri_date(m_e); break; } } catch (Exception Ex) { gestion_Erreur(Ex); } } Dans le cas du premier onglet (case 0:), il n‛y a rien à faire. Concernant celui des messages reçus (case 1:), je commence par vider le ListView (m_r.Items.Clear();); je stocke le chemin d‛accès à ces messages dans la variable ledossierr. J‛appelle la procédure scanne_fichier() en lui passant le ListView en question et le chemin des messages. Je créerai cette procédure par la suite.

Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 17


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

Son rôle sera de récupérer tous les informations des fichiers des messages et de les transmettre à la procédure avt_ContruitListe, elle aussi à construire. Puis, j‛appelle la procédure tri_date() qui a pour objectif de trier tous les messages par date. Elle aussi est à construire ultérieurement. Dans le cas de l‛onglet Eléments envoyés (case 2:), je fais exactement la même chose mais avec l‛autre ListView. ● Créer ensuite la procédure scanne_fichier(), comme suit: private void scanne_fichier(ListView laListe, string ledossier) { //Récupère les infos sur le répertoire passé en argument DirectoryInfo rep = new DirectoryInfo(ledossier); //Récupère les fichiers du répertoire FileInfo[] lesFichiers = rep.GetFiles(); foreach(FileInfo leFichier in lesFichiers) { if(leFichier.Name.Substring(leFichier.Name.Length-6)==»de.txt») { avt_ContruitListe(laListe, ledossier + leFichier.Name); } } } L‛explication est simple. A l‛aide des classes DirectoryInfo et FileInfo et d‛une boucle foreach, je passe en revue tous les fichiers du dossier passé en arguments (Soit recus, soit envoyes). Dès que je trouve un fichier au suffixe de, je le passe, avec le ListView à la procédure avt_ConstruitListe(). Cette dernière a pour rôle de récupérer toutes les informations (Date, destinataire, contenu...) du message passé en paramètre et de les afficher dans le ListView que je lui passe aussi en paramètres. ● Fort logiquement, créer la procédure avt_ContruitListe() comme indiqué ci-après:: private void avt_ContruitListe(ListView laListe, string nom_Fichier) { try { nom_Fichier = nom_Fichier.Substring(0, nom_Fichier.Length - 6); //Recup du destinataire... StreamReader lire = new StreamReader(nom_Fichier + «de.txt»); string de = lire.ReadLine(); lire.Close(); //Recup du sujet... lire = new StreamReader(nom_Fichier + «su.txt»); Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 18


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

string sujet = lire.ReadLine(); lire.Close(); //Recup de la date d’envoi... lire = new StreamReader(nom_Fichier + «da.txt»); string laDate = lire.ReadLine(); lire.Close(); sujet += «...»; construit_liste(laListe, de, sujet, laDate, nom_Fichier); } catch(Exception Ex) { gestion_Erreur(Ex); } } Là aussi, relativement simple. Je commence par extraire le nom commun à tous les fichiers de sauvegarde du même message (nom_Fichier = nom_Fichier.Substring(0, nom_Fichier.Length - 6);). Et puis pour chaque fichier au suffixe différent (su, de, da, pi), je récupère, dans une variable, l‛information qu‛il renferme à l‛aide d‛un objet StreamReader et de sa méthode ReadLine(). Et j‛appelle la procédure construit_liste() que nous avons déjà vu plus haut qui recrée le ListView. ● Double cliquer ensuite sur le bouton pe de l’onglet Eléments envoyés, pour créer son gestionnaire, ● Et, saisir son code comme suit: private void pe_Click(object sender, System.EventArgs e) { try { //Exécute la pièce jointe... string nom_Fichier = chemin + «envoyes\\» + piecee.Text; System.Diagnostics.Process.Start(nom_Fichier); } catch (Exception Ex) { gestion_Erreur(Ex); } } Ce bouton sert à ouvrir la pièce jointe à l‛aide du programme approprié, ce que je réalise grâce à l‛espace de noms Diagnostics. ● Faire de même avec le bouton po de l’onglet Boîte de réception:

Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 19


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

private void po_Click(object sender, System.EventArgs e) { try { //Exécute la pièce jointe... string nom_Fichier = chemin + «recus\\» + piecer.Text; System.Diagnostics.Process.Start(nom_Fichier); } catch (Exception Ex) { gestion_Erreur(Ex); } } Ensuite, j‛ai décidé d‛afficher les informations instantanées du message lorsque l‛utilisateur le sélectionne dans la liste, qu‛il s‛agisse de la liste des messages envoyés ou de celle des messages reçus. ● Créer le gestionnaire d’événement correspondant au changement de sélection dans la liste m_e, ● Et, saisir son code comme suit: private void m_e_SelectedIndexChanged(object sender, System.EventArgs e) { try { string nom_Fichier = m_e.FocusedItem.SubItems[3].Text + «pi.txt»; StreamReader lire = new StreamReader(nom_Fichier); string joint = lire.ReadLine(); lire.Close(); if(joint == «») { pe.Enabled = false; piecee.Text = «»; } else { pe.Enabled = true; piecee.Text = joint; } } catch (Exception Ex) { gestion_Erreur(Ex); }} Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 20


DreamLive : www.dreamlive.fr

Programmation C# - DotNet Communication réseau - Pièce jointe

Je récupère tout simplement le chemin et le nom du fichier joint correspondant au message sélectionné à l‛aide d‛un StreamReader. Et, j‛affiche ces informations dans le Label piecee. ● Faire exactement pareil avec le ListView m_r: private void m_r_SelectedIndexChanged(object sender, System.EventArgs e) { try { //Recherche de pièce jointe à la sélection d’un fichier... string nom_Fichier = m_r.FocusedItem.SubItems[3].Text + «pi.txt»; StreamReader lire = new StreamReader(nom_Fichier); string joint = lire.ReadLine(); lire.Close(); if(joint == «») { po.Enabled = false; piecer.Text = «»; } else { po.Enabled = true; piecer.Text = joint; } } catch (Exception Ex) { gestion_Erreur(Ex); } } ● Revenir sur l’onglet Boîte d’envoi et double cliquer sur le bouton Rompre, ● Puis, saisir son code comme suit: private void rompre_Click(object sender, System.EventArgs e) { try { leClient = new TcpClient(); jecoute.Stop(); module_Serveur.Abort(); module_Serveur = new Thread(new ThreadStart(Ecoute)); module_Serveur.Start(); etat.Panels[0].Text = «Serveur en attente de clients...»; Ces documents DreamLive sont libres de droits et ouverts à tous alors, profitez, partagez et appréciez ! Pour nous retrouver sur le Web : http://www.dreamlive.fr.

Page 21


C sharp c# communication réseau pièce jointe