Un exemple complet de transfert de fichiers basé sur le protocole Java Socket, terminé en fonction de la communication TCP.
En plus du transfert de fichiers binaires basé sur TCP, certaines compétences en programmation de Java Swing, programme de démonstration
Les fonctions principales sont implémentées comme suit:
Tout d'abord, jetons un coup d'œil à la relation entre toute la classe du dôme:
Ce qui suit est une explication détaillée des fonctions et des implémentations de code de chaque classe selon la figure ci-dessus:
Côté serveur:
La fonction de la classe FileTransFerserver est d'abord pour créer une prise de serveur sur le port 9999 et
Commencez à écouter la connexion. Les codes pertinents sont les suivants:
private void starterServer (int port) {try {serversocket = new serversocket (port); System.out.println ("Serveur démarré au port:" + port); while (true) {socket client = serversocket.accept (); // Bloqué et en attente de Socket Socket System.out.println ("Just Connected to" + client.getRemotesocketAddress ()); FileCeceIveTask Task = new FileCeveiveTask (client); bar.setValue (0); // Réinitialisez-le maintenant task.adddPropertyChangeListener (new PropertyChangeListERner () {public void PropertyChange (PropertyChangeEvent evt) {if ("progress" .equals (evt.getPropertyName ())) {Bar.SetValue ((Integer) evt.getNewValue ());}}}); tâche.execute (); }} catch (ioException e) {e.printStackTrace (); }}À propos de PropertyChangeListener, Java fournit une classe d'outils très puissante pour surveiller les changements de données dans tout modèle de bean. Le programme implémente le
La valeur de la propriété de progression de SwingWorker modifie la capture de l'événement, puis mettez à jour JProgressBar
Objet d'instance, réalise la rafraîchissement de l'interface utilisateur. Le code source complet de la classe FileTransFerserver est le suivant:
package com.gloomyfish.socket.tutorial.filetransfer; import java.awt.borderLayout; import java.awt.flowlayout; import java.awt.event.actionEvent; import java.awt.event.actionListener; import java.beans.propertychangeEvent; Importer java.beans.propertychangeListener; Importer java.io.ioException; import java.net.serversocket; import java.net.socket; import javax.swing.boxlayout; import javax.swing.jbutton; import javax.swing.jframe; import javax.swing.joptionpane; import javax.swing.jpanel; import javax.swing.jprogressbar; Classe publique FileTransFerserver étend JFrame implémente ActionListener {/ ** * * / public final static start start_svr = "start"; Public Final Static String shut_down_svr = "Shut Down"; public final static String end_flag = "eof"; Long SerialVersionUID privé statique statique = 1L; privé serversocket serversocket; JBUTTON STARTBTN privé; Bar privé JProgressBar; public fileTransFerserver () {super ("File Server"); IniTComponent (); setupListener (); } private void setupListener () {startBtn.addactionListener (this); } private void initComponent () {startBtn = new JButton (start_svr); JPanel ProgressPanel = new JPanel (); ProgressPanel.SetLayout (new BoxLayout (ProgressPanel, boxLayout.y_axis)); bar = new JProgressBar (); bar.setMinimum (0); bar.setMaxim (100); ProgressPanel.add (bar); getContentPane (). setLayout (new BorderLayout ()); Jpanel btnpanel = new JPanel (new FlowLayout (FlowLayout.Right)); btnpanel.add (startBtn); getContentPane (). Add (btnpanel, borderlayout.south); getContentPane (). Add (ProgressPanel, BorderLayout.Center); } private void starterServer (int port) {try {serversocket = new serversocket (port); System.out.println ("Serveur démarré au port:" + port); while (true) {socket client = serversocket.accept (); // Bloqué et en attente de Socket Socket System.out.println ("Just Connected to" + client.getRemotesocketAddress ()); FileCeceIveTask Task = new FileCeveiveTask (client); bar.setValue (0); // Réinitialisez-le maintenant task.adddPropertyChangeListener (new PropertyChangeListERner () {public void PropertyChange (PropertyChangeEvent evt) {if ("progress" .equals (evt.getPropertyName ())) {Bar.SetValue ((Integer) evt.getNewValue ());}}}); tâche.execute (); }} catch (ioException e) {e.printStackTrace (); }} public void showsuccess () {Bar.SetValue (100); JOptionPane.showMessageDialog (this, "Fichier a reçu avec succès!"); } @Override public void ActionperFormEd (ActionEvent e) {if (start_svr.equals (e.getActionCommand ())) {thread startThread = new Thread (new Runnable () {public void run () {Starterver (9999);}}); startThread.start (); startBtn.setEnabled (false); } else if (shut_down_svr.equals (e.getActionCommand ())) {} else {// ne rien faire ...}} public static void main (String [] args) {fileTransFerserver Server = new FileTransFerServer (); server.setDefaultCloseOperation (jframe.exit_on_close); server.setSize (400, 400); server.setResiSable (false); server.setVisible (true); }} FileReceIveTask est une classe d'acceptation de fichiers côté serveur:
Tout d'abord, obtenez le nom du fichier et la taille du fichier à partir du flux TCP établi, puis commencez à accepter les octets de contenu de fichier
Et écrivez dans le flux d'objets de fichier créé et vérifiez enfin si la taille du fichier est égale au flux d'octet écrit
Enfin, envoyez un message à l'expéditeur de fichiers pour indiquer à l'autre partie que le transfert de fichier est terminé et que le flux TCP peut être fermé.
Le code source complet de cette classe est le suivant:
package com.gloomyfish.socket.tutorial.filetransfer; Importer java.io.BufferedOutputStream; Importer java.io.BufferedOutputStream; import java.io.datainputStream; Importer java.io.file; Importer java.io.fileOutputStream; import java.io.outputStreamWriter; import java.net.socket; import javax.swing.swingworker; classe publique FileCeceIveTask étend SwingWorker <Integer, objet> {private socket _msocket; public filereCeiveTask (socket client) {this._msocket = client; } @Override Protected Integer DoinBackground () lève une exception {// Get File Meta Information DataNutStream Input = new DataRainputStream (_msocket.getInputStream ()); String filename = input.readutf (); int fileLength = (int) input.readlong (); // Nombre de fichiers de fichier total d'octets = nouveau fichier ("c: // utilisateurs // pêche // téléchargements" + file.separator + nom de fichier); BufferedOutputStream output = new BufferedOutStream (new FileOutputStream (fichier)); System.out.println ("Nom de fichier reçu =" + nom de fichier); System.out.println ("Reçu File size =" + fileLength / 1024 + "KB"); // Commencez à recevoir le contenu du fichier et écrivez-les Byte [] Content = New octet [2048]; int offset = 0; int numReadBytes = 0; while (offset <fileLength && (numReadBytes = input.read (contenu))> 0) {output.write (contenu, 0, numReadBytes); float Precent = 100.0f * ((float) offset) / ((float) fileLelength); SetProgress ((int) Precent); Offset + = numReadBytes; } System.out.println ("numReadBytes =" + numReadBytes); if (offset <fileLength) {numReadBytes = input.read (contenu); System.out.println ("numReadBytes =" + numReadBytes); System.out.println ("Erreur de contenu de fichier à côté serveur"); } else {System.out.println ("La tâche de réception du fichier a fait correctement"); } setProgress (100); // Dites au client de fermer la prise maintenant, nous recevons déjà le fichier avec succès !! BufferedWriter BufferedWriter = new BufferedWriter (new OutputStreamWriter (_msocket.getOutputStream ())); BufferedWriter.Write ("Done / R / N"); BufferedWriter.Flush (); // Fermez le fichier et le socket output.close (); _msocket.close (); retour 100; }} Client:
FileTransferClient est une classe d'interface utilisateur client qui implémente la connexion au serveur, puis sélectionne
Fichiers à transférer (images, PDF, documents Word, etc.). Sinon
Entrez les informations du serveur et une invite apparaîtra. Le port a été spécifié comme: 9999
Le bouton [Envoyer un fichier] ouvrira la zone de sélection des fichiers. Une fois que l'utilisateur a sélectionné le fichier à transférer, créez le
FileTransfertask Thread et commencez à exécuter le transfert de fichier. Le code d'interface utilisateur client est le suivant:
package com.gloomyfish.socket.tutorial.filetransfer; import java.awt.borderLayout; import java.awt.flowlayout; import java.awt.gridLayout; import java.awt.event.actionEvent; import java.awt.event.actionListener; import java.beans.propertychangeEvent; Importer java.beans.propertychangeListener; Importer java.io.file; Importer java.net.inetsocketAddress; Importer java.net.socketAddress; Importer javax.swing.borderfactory; import javax.swing.boxlayout; import javax.swing.jbutton; import javax.swing.jfilechooser; import javax.swing.jframe; import javax.swing.jlabel; import javax.swing.joptionpane; import javax.swing.jpanel; import javax.swing.jprogressbar; import javax.swing.jtextfield; / ** * J'écris habituellement des commentaires en anglais, et parfois j'écris également des commentaires chinois, mais je pense que l'écriture des commentaires de l'anglais * est plus unifié avec le code, et rien d'autre. * / classe publique FileTransferClient étend JFrame implémente ActionListener {/ ** * * / private static final long SerialVersionUID = 1l; Public Final Static String Send_cmd = "Send File"; public final static int minimum = 0; public final statique int maximum = 100; // Public Final Static String connect_cmd = "connect"; JBUTTON SENDFILEBTN privé; JEXTFIELD PRIVÉ SERVERFIELD; Jtexfield privé Portfield; Bar privé JProgressBar; public fileTransferClient () {super ("File Transfer Client"); INITCOMPONENTS (); } private void initComponents () {getContentPane (). setLayout (new BorderLayout ()); JPanel ProgressPanel = new JPanel (); progressPanel.setLayout(new BoxLayout(progressPanel, BoxLayout.Y_AXIS); bar = new JProgressBar(); progressPanel.add(bar); bar.setMinimum(MINIMUM); bar.setMaximum(MAXIMUM); JPanel serverSettingPanel = new JPanel(); serverSettingPanel.setLayout(new Gridlayout (2,2,5,5); ServerttingPanel.add (new JLabel ("Port serveur:"); btnpanel.add (SendFileBtn); GetContentPane (). ActionPerformed (ActionEvent E) {String Command = e.getActionCommand (); Chooser.ShowoPeNIDOG (null); tâche.AddProperTyChangeListEner (new PropertyChangeListEner () {public void PropertyChange (PropertyChangeEvent EVT) {if ("progress" .equals (evt.getProperToEname ())) {Bar.SetValue ((Integer) EVT.getNewValue ();}}}); } else {// ne rien}} public void showsuccess () {bar.setvalue (100); / ** * Assurez-vous que l'interface utilisateur a déjà des informations d'entrée correctes !!! Integer.Parseint); Client.SetSize (400, 400); Les principales fonctions implémentées par FileTransfertask sont:
Le code source complet de cette classe est le suivant:
package com.gloomyfish.socket.tutorial.filetransfer; Importer java.io.BufferedInputStream; Importer java.io.bufferedReader; import java.io.datainputStream; import java.io.dataOutputStream; Importer java.io.file; import java.io.fileInputStream; Importer java.io.ioException; Importer java.io.inputStreamReader; import java.net.socket; Importer java.net.socketAddress; import javax.swing.swingworker; classe publique FileTransFertask étend SwingWorker <Integer, objet> {Fichier privé selectedFile; Socket privé MSOCKET; Adresse privée de socketaddress; Parent de FileTransferClient privé; Public FileTransFerTask (fichier de fichier, adresse SocketAddress, propriétaire FileTransferClient / *, JProgressBar Progress * /) {this.address = adresse; this.selectedFile = fichier; msocket = new socket (); this.parent = propriétaire; } @Override Protected Integer DoinBackground () lève une exception {// Obtenez la taille du fichier Long Length = SelectedFile.Length (); if (longueur> Integer.max_value) {throw new ioException ("ne peut pas complètement lire le fichier" + selectedFile.getName () + "car il est trop long (" + longueur + "bytes, max pris en charge" + integer.max_value + ")"); } msocket.connect (adresse); // Créez le tableau d'octets pour maintenir les données de fichiers msocket.setsolinger (true, 60); DataOutputStream Dout = new DataOutputStream (msocket.getOutputStream ()); // Nous commençons maintenant à envoyer le fichier Meta Info. dout.writeUtf (selectedFile.getName ()); Dout.Writelong (longueur); Dout.flush (); // terminant le commentaire FiledAtApackage pdata = new FileDataPackage (); DatAnputStream est = new DatainputStream (new FileInputStream (selectedFile)); octet [] octets = nouveau octet [2048]; // Lire dans les octets int offset = 0; int numRead = 0; int fSize = (int) longueur; while (offset <fsize && (numRead = is.read (bytes, 0, bytes.length))> = 0) {pdata.setData (bytes, numRead); Dout.write (pdata.getPackageData (), 0, pdata.getPackagedata (). Length); Dout.flush (); Offset + = numRead; float Precent = 100.0f * ((float) offset) / ((float) fsize); SetProgress ((int) Precent); } System.out.println ("Total Send bytes =" + offset); // Assurez-vous que tous les octets ont été lus dans if (offset <fsize) {lancer une nouvelle ioException ("ne peut pas complètement transférer le fichier" + selectedFile.getName ()); } msocket.shutdownoutput (); // Recevoir le transfert de fichier Message avec succès de la connexion BufferedInputStream StreamReader = new BufferedInputStream (msocket.getInputStream ()); BufferedReader BufferedReader = new BufferedReader (new InputStreamReader (StreamReader)); String donemsg = bufferedReader.Readline (); if ("fait" .equals (donemsg)) {parent.showsuccess (); } // Fermez le flux d'entrée de fichier setProgress (100); // Dout.Close (); msocket.close (); is.close (); System.out.println ("Fermez-le maintenant ..."); retour 100; }}La classe de paquets est la suivante, non expliqué!
package com.gloomyfish.socket.tutorial.filetransfer; / ** * Il s'agit d'un protocole de transfert de fichiers très simple sur TCP Socket * / classe publique FileDataPackage {private int DataLegment; // la durée des données dans le paquet, deux octets octets privés [] databuff; // Les données maximales du paquet, le Meici ne dépassera pas 2048 octets publics public statique final byte [] eof = new octet [] {'e', 'o', 'f'}; public filedAtApackage () {datalngle = 0; databuff = new octet [2048]; } octet public [] getPackageData () {byte [] pdata = new byte [datalngle]; // End Comment commentaire System.ArrayCopy (Databuff, 0, Pdata, 0, Datal Length); retour pdata; } public void setData (byte [] data, int bsize) {datalngle = bsize; for (int i = 0; i <databuff.length; i ++) {if (i <bsize) {databuff [i] = data [i]; } else {databuff [i] = ''; }}}}Le nombre maximum d'octets envoyés par temps est de 2048 octets. L'effet final du programme est le suivant (win7 + jdk6u30):
Ce qui précède concerne cet article, j'espère qu'il sera utile à l'apprentissage de tout le monde.