Ein vollständiges Beispiel für die Dateiübertragung basierend auf dem Java -Socket -Protokoll, das basierend auf der TCP -Kommunikation abgeschlossen wurde.
Zusätzlich zu TCP-basierten Binärdateitransfer, einigen Programmierkenntnissen von Java Swing, Demo-Programm
Die Hauptfunktionen werden wie folgt implementiert:
Schauen wir uns zunächst die Beziehung zwischen der gesamten Kuppelklasse an:
Das Folgende ist eine detaillierte Erklärung der Funktionen und Codeimplementierungen jeder Klasse gemäß der obigen Abbildung:
Serverseite:
Die Funktion der Filetransferserver -Klasse erstellt zunächst einen Server -Socket auf Port 9999 und
Hören Sie sich die Verbindung an. Die relevanten Codes sind wie folgt:
private void startserver (int port) {try {serverSocket = new ServerSocket (Port); System.out.println ("Server am Port gestartet:" + port); while (true) {Socket Client = ServerSocket.accept (); // blockiert und auf das Einkommenssocket system.out.println ("nur verbunden mit" + client.getRemotesocketadDress ()); FileReceivetask Task = new FileReceivetask (Client); bar.setValue (0); // IT Now task.addPropertyChangelistener (New PropertyChangelistener () {public void propertyChange (PropertyChangeEvent evt) {if ("progress" .equals (evt.getPropertyName ())) {bar.setValue ((Intiere); task.execute (); }} catch (ioException e) {e.printstacktrace (); }}Über PropertyChangelistener bietet Java eine sehr leistungsstarke Werkzeugklasse, um Datenänderungen in jedem Bean -Modell zu überwachen. Das Programm implementiert die
Die Ereigniserfassung des Swingworker -Fortschritts -Eigenschaftswertes ändert sich und aktualisiere die JProgressBar
Instanzobjekt, realisiert die Aktualisierung der UI. Der vollständige Quellcode der Filetransferserver -Klasse lautet wie folgt:
Paket 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; Import Java.beans.PropertyChangelistener; importieren java.io.ioException; importieren java.net.serversocket; importieren java.net.socket; importieren javax.swing.boxlayout; import Javax.swing.jbutton; importieren javax.swing.jframe; import Javax.swing.joptionpane; import Javax.swing.jpanel; import Javax.swing.jprogressbar; öffentliche Klasse filetransferserver erweitert JFrame implementiert actionListener { / ** * * / public Final Static String start_svr = "start"; öffentliche endgültige statische String schalt_down_svr = "Shut Down"; public Final Static String end_flag = "eof"; private statische endgültige lange Serialversionuid = 1L; Private ServerSocket ServerSocket; Privat Jbutton StartBtn; Privat JProgressBar Bar; public filetransferserver () {Super ("Dateiserver"); initComponent (); setUplistener (); } private void setUplistener () {startBtn.addactionListener (this); } private void initComponent () {startBtn = new Jbutton (start_svr); JPanel ProgressPanel = new Jpanel (); progresorpanel.setLayout (neuer BoxLayout (progressPanel, boxLayout.y_axis)); bar = new JProgressBar (); bar.setminimum (0); bar.setMaximum (100); progresorpanel.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 startserver (int port) {try {serversocket = new ServerSocket (port); System.out.println ("Server am Port gestartet:" + port); while (true) {Socket Client = ServerSocket.accept (); // blockiert und auf das Einkommenssocket system.out.println ("nur verbunden mit" + client.getRemotesocketadDress ()); FileReceivetask Task = new FileReceivetask (Client); bar.setValue (0); // IT Now task.addPropertyChangelistener (New PropertyChangelistener () {public void propertyChange (PropertyChangeEvent evt) {if ("progress" .equals (evt.getPropertyName ())) {bar.setValue ((Intiere); task.execute (); }} catch (ioException e) {e.printstacktrace (); }} public void showsuccess () {bar.setValue (100); JOPTIONPANE.SHOWMESSAGEDIALOG (dies, "Datei erfolgreich erhalten!"); } @Override public void actionPerformed (actionEvent e) {if (start_svr.equals (e.getActionCommand ()) {Thread startThread = neuer Thread (new Runnable () {public void run () {startserver (9999);}}); startThread.start (); startBtn.setEnabled (false); } else if (shut_down_svr.equals (e.getActionCommand ()) {} else {// nichts tun ...}} public static void main (String [] args) {filetransferserver Server = new FileTransFerServer (); server.setDefaultCloseOperation (jframe.exit_on_close); Server.SetSize (400, 400); server.setResizable (false); server.setVisible (true); }} FileReceivetask ist eine Dateiakzeptanzklasse auf der Serverseite:
Holen Sie sich zunächst den Dateinamen und die Dateigröße aus dem festgelegten TCP -Stream und akzeptieren Sie dann Bytes von Dateiinhalten
Und schreiben
Senden Sie schließlich eine Nachricht an den Dateiabsender, um der anderen Partei mitzuteilen, dass die Dateiübertragung abgeschlossen ist und der TCP -Stream geschlossen werden kann.
Der vollständige Quellcode dieser Klasse lautet wie folgt:
Paket com.gloomyfish.socket.tutorial.filetRansfer; importieren java.io.bufferedOutputStream; importieren java.io.bufferedOutputStream; importieren java.io.datainputstream; Import Java.io.file; importieren java.io.fileoutputStream; importieren java.io.outputStreamwriter; importieren java.net.socket; import Javax.swing.swingworker; öffentliche Klasse fileReceivetask erweitert Swingworker <Integer, Objekt> {privater Socket _msocket; public fileReceivetask (Socket Client) {this._msocket = client; } @Override Protected Integer doInbackground () löst Ausnahme aus {// Datei Meta -Informationen DataNputStream input = new DataNputStream (_msocket.getInputStream ()); String Dateiname = input.readutf (); int filelength = (int) input.readlong (); // Anzahl der gesamten Bytes -Datei Datei = neue Datei ("c: // user // fish // downloads" + file.separator + Dateiname); PufufferedOutputStream output = new bufferedOutputStream (New FileOutputStream (Datei)); System.out.println ("empfangene Datei name =" + Dateiname); System.out.println ("empfangene Datei size =" + filelength/1024 + "kb"); // den Inhalt der Datei empfangen und sie byte [] content = New Byte [2048] schreiben; int offset = 0; int numreadBytes = 0; while (offset <filelength && (numreadBytes = input.read (Inhalt))> 0) {output.write (Inhalt, 0, numreadBytes); float precent = 100.0f * ((float) offset)/((float) filelength); setProgress ((int) precent); offset += numreadBytes; } System.out.println ("numreadBytes =" + numreadBytes); if (offset <filelength) {numreadBytes = input.read (Inhalt); System.out.println ("numreadBytes =" + numreadBytes); System.out.println ("Dateiinhaltsfehler auf der Serverseite"); } else {system.out.println ("Dateiempfänger -Aufgabe hat korrekt erledigt"); } setProgress (100); // den Client auffordere, den Socket jetzt zu schließen, wir erhalten die Datei bereits erfolgreich !! BufferedWriter bufferedWriter = neuer bufferedWriter (neuer outputStreamwriter (_msocket.getOutputStream ())); bufferedWriter.write ("Done/r/n"); bufferedWriter.flush (); // Schließen Sie die Datei und die Socket -Ausgabe.CLOSE (); _msocket.close (); Rückkehr 100; }} Kunde:
FileTransferclient ist eine Client -UI -Klasse, die die Verbindung zum Server implementiert und dann ausgewählt wird
Dateien zu übertragen (Bilder, PDFs, Wortdokumente usw.). Wenn nicht
Geben Sie die Serverinformationen ein und eine Eingabeaufforderung wird angezeigt. Der Port wurde als: 9999 angegeben
Die Schaltfläche [Datei senden] wird das Feld "Dateiauswahl" geöffnet. Nachdem der Benutzer die zu übertragende Datei ausgewählt hat, erstellen Sie die
Filetransfertask -Thread und mit der Ausführung der Dateiübertragung. Der Client -UI -Code lautet wie folgt:
Paket com.gloomyfish.socket.tutorial.filetRansfer; Import Java.awt.BorderLayout; import Java.awt.flowlayout; importieren java.awt.gridlayout; import Java.awt.event.ActionEvent; import Java.awt.event.ActionListener; Import Java.beans.PropertyChangeEvent; Import Java.beans.PropertyChangelistener; Import Java.io.file; importieren java.net.inetsocketaddress; importieren java.net.socketaddress; import Javax.swing.BorderFactory; importieren javax.swing.boxlayout; import Javax.swing.jbutton; import Javax.swing.jfilechooser; importieren javax.swing.jframe; import Javax.swing.jlabel; import Javax.swing.joptionpane; import Javax.swing.jpanel; import Javax.swing.jprogressbar; importieren javax.swing.jtextfield; /*** Ich schreibe normalerweise englische Kommentare, und gelegentlich schreibe ich auch chinesische Kommentare, aber ich denke, dass das Schreiben von Englisch* Kommentare mit dem Code eher einheitlich sind und sonst nichts. */ public class filetransferclient erweitert JFrame implementiert actionListener {/ ** * */ private statische endgültige long serialversionuid = 1l; öffentliche endgültige statische String send_cmd = "Datei senden"; öffentliches endgültiges statisches int minimum = 0; öffentliches endgültiges statisches int maximal = 100; // Public Final Static String Connect_cmd = "Connect"; Privat Jbutton SendFilebtn; private JTextField Serverfield; Private Jtextfield Portfield; Privat JProgressBar Bar; public filetransferclient () {Super ("Dateitransfer 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); GridLayout (2,2,5,5); ServersettPanel.Add (neuer JLabel ("Server -Port:")); btnpanel.add (sendFilebtn); @Override public voidPerformed (actionEvent e) {String -Befehl = E.GetactionCommand (); status = chooser.showopendialog (null); Task.AddPropertyChangelistener (New PropertyChangelistener () {public void PropertyChange (PropertyChangeEvent evt) {if ("Fortschritt" .Equals (evt.getPropertyName ())) Ausführung}} else {// nichts}} public void showsuccess () {bar.setValue (100); Integer.ParseInt (portfield.GetText (). TRIM ()); port.length () == 0) {return true; client.setDefaultCloseOperation (jframe.exit_on_close); Die von Filetransfertask implementierten Hauptfunktionen sind:
Der vollständige Quellcode dieser Klasse lautet wie folgt:
Paket com.gloomyfish.socket.tutorial.filetRansfer; import Java.io.BufferedInputStream; Import Java.io.BufferedReader; importieren java.io.datainputstream; importieren java.io.dataoutputStream; Import Java.io.file; import Java.io.FileInputStream; importieren java.io.ioException; importieren java.io.inputStreamReader; importieren java.net.socket; importieren java.net.socketaddress; import Javax.swing.swingworker; öffentliche Klasse Filetransfertask erweitert Swingworker <Integer, Objekt> {private Datei SelectedFile; private Socket MSocket; private Socketaddress -Adresse; privates filetransferlienter Elternteil; public filetransfertask (Dateidatei, SocketAddress -Adresse, FileTransferClient -Eigentümer /*, JProgressBar -Fortschritt* /) {this.address = address; this.selectedFile = Datei; msocket = new Socket (); this.Parent = Besitzer; } @Override Protected Integer doInbackground () löst eine Ausnahme aus {// Die Größe der Datei Long Länge = SelectedFile.length (); if (Länge> Integer.max_value) {neue IOException werfen ("konnte die Datei nicht vollständig lesen" + SelectedFile.getName () + ", da es zu lang ist (" + länge + "Bytes, max unterstützt" + Integer.max_value + "); } msocket.connect (Adresse); // Erstellen Sie das Byte -Array, um die Dateidaten msocket.setSolinger (true, 60) zu halten. DataOutputStream dout = new DataOutputStream (msocket.getOutputStream ()); // Jetzt senden wir die Datei -Meta -Informationen. Dout.WriteUTF (selectedFile.getName ()); Dout.WriteLong (Länge); dout.flush (); // End -Kommentar fehlgeschlagene pdata = new farrEedatapackage (); DataNputStream ist = neuer DataNputStream (neuer FileInputStream (SelectedFile)); byte [] bytes = neues byte [2048]; // im Bytes int offset = 0 lesen; int numread = 0; int fSize = (int) Länge; while (offset <fsize && (numread = is.read (bytes, 0, bytes.length))> = 0) {pdata.setData (bytes, numread); Dout.Write (pdata.getPackagedata (), 0, pdata.getPackagedata (). Länge); dout.flush (); Offset += numread; float precent = 100,0f * ((float) offset)/((float) fsire); setProgress ((int) precent); } System.out.println ("Gesamtsende Bytes =" + Offset); // Stellen Sie sicher, dass alle Bytes in if (offset <fsize) {neue IOException werfen ("konnte die Datei nicht vollständig übertragen" + SelectedFile.getName ()); } msocket.shutDownoutput (); // die Dateiübertragung erfolgreich von Connection BuferedInputStream StreamReader = New BuferedInputStream (msocket.getInputStream ()) erhalten; BufferedReader BufferedReader = neuer BufferedReader (neuer InputStreamReader (StreamReader)); String donemsg = bufferedReader.readline (); if ("done" .equals (donemsg)) {parent.showsuccess (); } // Schließen Sie den Dateieingabestream SetProgress (100); // dout.close (); msocket.close (); IS.CLOSE (); System.out.println ("Jetzt schließen ..."); Rückkehr 100; }}Die Paketklasse ist wie folgt, nicht erklärt!
Paket com.gloomyfish.socket.tutorial.filetRansfer; / ** * Dies ist ein sehr einfaches Dateiübertragungsprotokoll über TCP -Socket */ öffentliche Klasse FELDATAPACKAGE {private int DataLength; // Die Datenlänge im Paket, zwei Bytes private Byte [] Datenpuff; // Die maximalen Daten im Paket darf die Meici 2048 Bytes öffentliches endgültiges statisches Byte [] eof = new Byte [] {'e', 'o', 'f'} nicht überschreiten; public farrEedatapackage () {datalength = 0; DataBuff = neues Byte [2048]; } public byte [] getPackagedata () {byte [] pdata = new byte [datalength]; // End -Kommentarsystem.ArrayCopy (Datenpuff, 0, Pdata, 0, Datalength); return pdata; } public void setData (byte [] data, int bSize) {datalength = bsize; für (int i = 0; i <DataBuff.length; i ++) {if (i <bsize) {DatenBuff [i] = data [i]; } else {databuff [i] = ''; }}}}Die maximale Anzahl von Bytes pro Zeit beträgt 2048 Bytes. Der endgültige laufende Effekt des Programms ist wie folgt (Win7 + JDK6U30):
Das Obige dreht sich alles um diesen Artikel, ich hoffe, es wird für das Lernen aller hilfreich sein.