Un ejemplo completo de transferencia de archivos basado en el protocolo de socket Java, completado basado en la comunicación TCP.
Además de la transferencia de archivos binarios basados en TCP, algunas habilidades de programación de Java Swing, programa de demostración
Las funciones principales se implementan de la siguiente manera:
Primero, echemos un vistazo a la relación entre toda la clase Dome:
La siguiente es una explicación detallada de las funciones e implementaciones de código de cada clase de acuerdo con la figura anterior:
Lado del servidor:
La función de FileTransFerServer Class es la primera vez en crear un socket de servidor en el puerto 9999 y
Comience a escuchar la conexión. Los códigos relevantes son los siguientes:
privado void startserver (int puerto) {try {Serversocket = new Serversocket (puerto); System.out.println ("Servidor iniciado en el puerto:" + puerto); while (true) {Socket Client = Serversocket.accept (); // Bloqueado y esperando el socket de ingresos System.out.println ("recién conectado a" + client.getRemotesocketAddress ()); FileReceIveTask Task = new FileReceIveTask (Cliente); bar.setValue (0); // reiniciarlo ahora task.AddPropertyChangeListener (nuevo PropertyChangeListener () {public void PropertyChange (PropertyChangeEvent Evt) {if ("progreso" .equals (evt.getPropertyname ())) {bar.setValue ((integer) evt.getNewValue ();}}}); task.exCute (); }} catch (ioException e) {E.PrintStackTrace (); }}Acerca de PropertyChangeListener, Java proporciona una clase de herramientas muy potente para monitorear los cambios de datos en cualquier modelo de frijoles. El programa implementa el
La propiedad de la propiedad de progreso de Swingworker cambia el valor de la captura de eventos, luego actualiza JProgressBar
Objeto de instancia, realiza la actualización de la interfaz de usuario. El código fuente completo de FileTransFerServer es el siguiente:
paquete com.gloomyfish.socket.tutorial.filetransfer; import java.awt.borderlayut; import java.awt.flowlayout; import java.awt.event.actionEvent; import java.awt.event.actionListener; import java.beans.propertychangeEvent; import java.beans.propertychangelistener; import 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; Public Class FiletransFerServer extiende Jframe implementos ActionListener { / ** * * / public Final Static String start_svr = "inicio"; Public final static string shut_down_svr = "apagar"; Public final static string end_flag = "eof"; Private static final Long SerialVersionUid = 1L; Servidor de servidores privado Servidor de machos; Privado JButton StartBtn; Bar privado JProgressbar; public FiletransFerServer () {super ("servidor de archivos"); initComponent (); setUplistener (); } private void setUplistener () {startBtn.addactionListener (this); } private void initcomponent () {startBtn = new JButton (start_svr); JPanel ProgressPanel = new JPanel (); Progrespanel.setLayout (nuevo BoxLayout (ProgressPanel, BoxLayout.y_axis)); bar = new JProgressBar (); bar.setminimum (0); bar.setMaximum (100); ProgressPanel.add (bar); getContentPane (). SetLayout (new BorderLayout ()); Jpanel btnpanel = new JPanel (nuevo FlowLayout (FlowLayout.Right)); btnpanel.add (startBtn); getContentPane (). ADD (BTNPANEL, BorderLayout.South); getContentPane (). ADD (ProgressPanel, BorderLayout.Center); } private void startserver (int puerto) {try {Serversocket = new Serversocket (puerto); System.out.println ("Servidor iniciado en el puerto:" + puerto); while (true) {Socket Client = Serversocket.accept (); // Bloqueado y esperando el socket de ingresos System.out.println ("recién conectado a" + client.getRemotesocketAddress ()); FileReceIveTask Task = new FileReceIveTask (Cliente); bar.setValue (0); // reiniciarlo ahora task.AddPropertyChangeListener (nuevo PropertyChangeListener () {public void PropertyChange (PropertyChangeEvent Evt) {if ("progreso" .equals (evt.getPropertyname ())) {bar.setValue ((integer) evt.getNewValue ();}}}); task.exCute (); }} catch (ioException e) {E.PrintStackTrace (); }} public void showsUccess () {Bar.SetValue (100); JoptionPane.ShowMessEdialog (este ", el archivo recibido con éxito!"); } @Override public void ActionPerformed (ActionEvent e) {if (start_svr.equals (e.getActionCommand ())) {Thread startThread = new Thread (new Runnable () {public void run () {startingerver (9999);}}); startThread.start (); startBtn.SetEnabled (falso); } else if (shut_down_svr.equals (e.getActionCommand ())) {} else {// no hacer nada ...}} public static void main (string [] args) {fileTransFerserver Server = new FileTransFerserver (); servidor.setDefaultCloseOperation (jframe.exit_on_close); servidor.setsize (400, 400); servidor.setResizable (falso); servidor.setVisible (verdadero); }} FileReVeTask es una clase de aceptación de archivos en el lado del servidor:
Primero, obtenga el nombre del archivo y el tamaño del archivo de la transmisión TCP establecida, y luego comience a aceptar bytes de contenido del archivo
Y escriba en la transmisión del objeto de archivo creado y finalmente verifique si el tamaño del archivo es igual al flujo de byte escrito
Finalmente, envíe un mensaje al remitente del archivo para decirle a la otra parte que se completa la transferencia de archivos y que la transmisión TCP puede cerrarse.
El código fuente completo de esta clase es el siguiente:
paquete com.gloomyfish.socket.tutorial.filetransfer; import java.io.bufferedOutputStream; import java.io.bufferedOutputStream; import java.io.datainputstream; import java.io.file; import java.io.fileOutputStream; import java.io.outputstreamwriter; import java.net.socket; import javax.swing.swingworker; Public Class FilereceItask extiende SwingWorker <Integer, Object> {private Socket _msocket; Public FileReceIveTask (Socket Client) {this._msocket = client; } @Override Integer protegido doinBackground () lanza la excepción {// Obtener el archivo meta información datainPutStream input = new DataInputStream (_msocket.getInputStream ()); Cadena filename = input.readutf (); int filelength = (int) input.readLong (); // Número de archivo de archivo bytes total = nuevo archivo ("c: // users // pesh // descarga" + file.separator + nombre de archivo); BufferedOutputStream output = new BufferedOutputStream (nuevo FileOutputStream (archivo)); System.out.println ("recibió el nombre del archivo =" + nombre de archivo); System.out.println ("Size de archivo recibido =" + Filelength/1024 + "Kb"); // Comience a recibir el contenido del archivo y escríbelos byte [] content = new byte [2048]; int offset = 0; int numReadBytes = 0; while (offset <filelength && (numReadBytes = input.read (content))> 0) {output.write (content, 0, numReadBytes); float prelegente = 100.0f * (((flotante) desplazamiento)/(((float) Filelgentil); setProgress ((int) pracent); offset += numReadBytes; } System.out.println ("numreadbytes =" + numreadbytes); if (offset <fileLength) {numReadBytes = input.read (content); System.out.println ("numReadBytes =" + numReadBytes); System.out.println ("Error de contenido del archivo en el lado del servidor"); } else {System.out.println ("La tarea de recepción del archivo se ha hecho correctamente"); } setProgress (100); // ¡Dígale al cliente que cierre el socket ahora, ya recibimos el archivo con éxito! BufferedWriter BufferedWriter = new BufferedWriter (new OutputStreamWriter (_msocket.getOutputStream ())); BufferedWriter.Write ("Done/R/N"); bufferedwriter.flush (); // cierre el archivo y la salida de socket.close (); _msocket.close (); regresar 100; }} Cliente:
FiletransferClient es una clase de interfaz de usuario del cliente que implementa la conexión al servidor y luego selecciona
Archivos a transferir (imágenes, PDF, documentos de Word, etc.). Si no
Ingrese la información del servidor y aparecerá un mensaje. El puerto se ha especificado como: 9999
El botón [Enviar archivo] abrirá el cuadro de selección de archivos. Después de que el usuario seleccione el archivo a transferir, cree el
FileTransferTask Hilo y comience a ejecutar la transferencia de archivos. El código de interfaz de usuario del cliente es el siguiente:
paquete com.gloomyfish.socket.tutorial.filetransfer; import java.awt.borderlayut; import java.awt.flowlayout; import 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; import java.net.InetSocketAddress; import java.net.socketaddress; import 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; /*** Por lo general, escribo comentarios en inglés, y ocasionalmente también escribo comentarios chinos, pero creo que escribir comentarios en inglés* están más unificados con el código y nada más. */ public class FiletransferClient extiende jframe implementos ActionListener {/ ** * */ private static final Long SerialVersionUid = 1l; Public final static string send_cmd = "enviar archivo"; Public final estática int mínimo = 0; Public final estática int Maximum = 100; // cadena estatica final pública Connect_CMD = "Connect"; Privado JButton SendFileBtn; privado jtextfield serverfield; Privado JTextfield Portfield; Bar privado JProgressbar; public FiletransferClient () {super ("Cliente de transferencia de archivos"); 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 (NEWNE GridLayout (2,2,5,5); JLABEL ("Puerto de servidor:"); GetContentPane (). ADD (SERVERSETINGPANEL, BorderLayout.north); E.GetActionCommand (); JFILECHOOSER.Approve_OPTION) {Archivo F = Chooser.getSelectedFile (); Void Property (PropertyChangeEvent Evt) {if ("progreso" .equals (evt.getPropertyname ()) {Bar.SetValue ((Integer) Evt.getNewValue ()); Bar.SetValue (100); privado boolean checkNull () {String ServerName = ServerField.Gettext (); Catch (NumberForme NE) {ne.PrintStackTrace (); Client.pack (); Las principales funciones implementadas por FiletransferTask son:
El código fuente completo de esta clase es el siguiente:
paquete com.gloomyfish.socket.tutorial.filetransfer; import java.io.bufferedInputStream; import java.io.bufferedReader; import java.io.datainputstream; import java.io.dataOutputStream; import java.io.file; import java.io.fileInputStream; import java.io.ioException; import java.io.inputstreamreader; import java.net.socket; import java.net.socketaddress; import javax.swing.swingworker; Public Class FiletransferTask extiende SwingWorker <Integer, Object> {archivo privado selectedFile; Socket privado Msocket; dirección privada de enchufeaddress; Padre privado FiletransferClient; public FiletransferTask (archivo de archivo, dirección de SocketAddress, propietario de FiletransferClient /*, jprogressbar progress* /) {this.address = dirección; this.selectedFile = file; msocket = new Socket (); this.parent = propietario; } @Override Integer protegido doinBackground () lanza la excepción {// Obtener el tamaño del archivo Long Longitud = selectedFile.length (); if (longitud> integer.max_value) {throle new ioException ("no se pudo leer completamente el archivo" + selectedFile.getName () + "como es demasiado largo (" + longitud + "bytes, max admitido" + integer.max_value + ")"); } msocket.connect (dirección); // Cree la matriz de bytes para mantener los datos del archivo msocket.setsolinger (true, 60); DatautputStream dout = new DataOutputStream (msocket.getOutputStream ()); // Ahora comenzamos a enviar la información meta del archivo. dout.writeutf (selectedFile.getName ()); dout.writelong (longitud); dout.flush (); // finalizar el comentario FileDatApAckage PDATA = new FileDAtApAckage (); DataInputStream es = nuevo DataInputStream (nuevo FileInputStream (selectedFile)); byte [] bytes = new Byte [2048]; // Leer en el bytes int offset = 0; int numread = 0; int fsize = (int) longitud; while (offset <fsize && (numread = is.read (bytes, 0, bytes.length))> = 0) {pdata.setData (bytes, numread); dout.write (pdata.getPackageAtA (), 0, pdata.getPackageGe (). Longitud); dout.flush (); offset += numread; float prelegente = 100.0f * ((flotante) desplazamiento)/((float) fsize); setProgress ((int) pracent); } System.out.println ("Total Send bytes =" + offset); // Asegúrese de que todos los bytes se hayan leído en if (offset <fsize) {lanzar nueva IOException ("no se pudo transferir completamente el archivo" + selectedFile.getName ()); } msocket.shutdodoutput (); // Recibe el mensaje de transferencia de archivo con éxito de la conexión BufferedInputStream StreamReader = new BufferedInputStream (msocket.getInputStream ()); BufferedReader BufferedReader = new BufferedReader (new InputStreamReader (StreamReader)); Cadena donemsg = bufferedReader.readline (); if ("hecho" .equals (donemsg)) {parent.showsuccess (); } // Cierre el flujo de entrada de archivo setProgress (100); // dout.close (); msocket.close (); is.close (); System.out.println ("CÁRCER AHORA ..."); regresar 100; }}¡La clase de paquete es la siguiente, no explicada!
paquete com.gloomyfish.socket.tutorial.filetransfer; / ** * Este es un protocolo de transferencia de archivos muy simple a través de TCP Socket */ Public Class FileDAtapAckage {private int dataLength; // La longitud de los datos en el paquete, dos bytes byte privado [] de datos; // Los datos máximos en el paquete, el Meici no excederá 2048 bytes públicos Byte estático final [] eof = new byte [] {'e', 'o', 'f'}; public FileDatApAckage () {DataLength = 0; databuff = nuevo byte [2048]; } public byte [] getPackageAtA () {byte [] pdata = new Byte [DataLength]; // finalizar el sistema de comentarios. devolver pdata; } public void setData (byte [] data, int bsize) {dataLength = bSize; for (int i = 0; i <databuff.length; i ++) {if (i <bsize) {databuff [i] = data [i]; } else {databuff [i] = ''; }}}}El número máximo de bytes enviados por tiempo es de 2048 bytes. El efecto de ejecución final del programa es el siguiente (win7 + jdk6u30):
Lo anterior se trata de este artículo, espero que sea útil para el aprendizaje de todos.