Um exemplo completo de transferência de arquivos com base no protocolo de soquete Java, concluído com base na comunicação TCP.
Além da transferência de arquivos binários baseados em TCP, algumas habilidades de programação do programa de demonstração Java Swing,
As principais funções são implementadas da seguinte forma:
Primeiro, vamos dar uma olhada no relacionamento entre toda a aula de cúpula:
A seguir, é apresentada uma explicação detalhada das funções e implementações de código de cada classe de acordo com a figura acima:
Lado do servidor:
A função da classe FileTransferServer é a primeira a criar um soquete do servidor na porta 9999 e
Comece a ouvir a conexão. Os códigos relevantes são os seguintes:
private void startServer (int porta) {try {serverSocket = new ServerSocket (porta); System.out.println ("Servidor iniciado na porta:" + porta); while (true) {socket client = serversocket.accept (); // bloqueado e aguardando o soquete de renda System.out.println ("Apenas conectado a" + client.getRemoteSocketAddress ()); FileReCeIVETask tarefa = new FileReCeIVETask (cliente); bar.setValue (0); // redefini -lo agora task.addPropertyChangelistener (new PropertyChangelistener () {public void PropertyChange (PropertyChangeEvent evt) {if ("Progress" .equals (evt.getPropertyName ())) {bar.setValue (integger) eVTNewvalue ();}; tarefa.Execute (); }} catch (ioexception e) {e.printStackTrace (); }}Sobre o PropertyChangelistener, o Java fornece uma classe de ferramentas muito poderosa para monitorar alterações de dados em qualquer modelo de feijão. O programa implementa o
Captura de eventos do valor da propriedade do SwingWorker Progress, depois atualize JProgressBar
Objeto de instância, percebe a atualização da interface do usuário. O código -fonte completo da classe FileTransferServer é o seguinte:
pacote com.gloomyfish.socket.tutorial.FileTransfer; importar java.awt.borderlayout; importar java.awt.flowlayout; importar java.awt.event.actionEvent; importar java.awt.event.actionListener; importar java.beans.propertyChangeEvent; importar java.beans.propertyChangelistener; importar java.io.ioException; importar java.net.serversocket; importar java.net.socket; importar javax.swing.boxlayout; importar javax.swing.jbutton; importar javax.swing.jframe; importar javax.swing.JOptionPane; importar javax.swing.jpanel; importar javax.swing.jProgressBar; classe pública FileTransFerServer estende o jframe implementa o ActionListener { / ** * * / public final static string string_svr = "start"; public final Static String Shut_down_svr = "Desligar"; public final Static String end_flag = "eof"; private estático final serialversionUid = 1L; Serversocket ServerSocket privado; private JButton Startbtn; Barra JProgressBar Private; public fileTransferServer () {super ("servidor de arquivo"); 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.setMaximum (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 startServer (int porta) {try {serverSocket = new ServerSocket (porta); System.out.println ("Servidor iniciado na porta:" + porta); while (true) {socket client = serversocket.accept (); // bloqueado e aguardando o soquete de renda System.out.println ("Apenas conectado a" + client.getRemoteSocketAddress ()); FileReCeIVETask tarefa = new FileReCeIVETask (cliente); bar.setValue (0); // redefini -lo agora task.addPropertyChangelistener (new PropertyChangelistener () {public void PropertyChange (PropertyChangeEvent evt) {if ("Progress" .equals (evt.getPropertyName ())) {bar.setValue (integger) eVTNewvalue ();}; tarefa.Execute (); }} catch (ioexception e) {e.printStackTrace (); }} public void showsuccess () {bar.setValue (100); JoptionPane.showMessagedialog (isto, "arquivo recebido com sucesso!"); } @Override public void ActionPerformed (ActionEvent e) {if (start_svr.equals (e.getActionCommand ())) {thread startThread = new Thread (new runnable () {public void run () {startServer (9999);}}); startThread.start (); startbtn.setEnabled (false); } else if (Shut_down_svr.equals (E.GetActionCommand ())) {} else {// não faz nada ...}} 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 é uma classe de aceitação de arquivo no lado do servidor:
Primeiro, obtenha o nome do arquivo e o tamanho do arquivo do fluxo TCP estabelecido e depois comece a aceitar bytes de conteúdo do arquivo
E escreva no fluxo de objeto de arquivo criado e, finalmente, verifique se o tamanho do arquivo é igual ao fluxo de bytes escrito
Por fim, envie uma mensagem ao remetente do arquivo para informar à outra parte que a transferência de arquivo está concluída e o fluxo TCP pode ser fechado.
O código -fonte completo desta classe é o seguinte:
pacote com.gloomyfish.socket.tutorial.FileTransfer; importar java.io.bufferedOutputStream; importar java.io.bufferedOutputStream; importar java.io.datainputStream; importar java.io.file; importar java.io.fileOutputStream; importar java.io.OutputStreamWriter; importar java.net.socket; importar javax.swing.swingworker; classe pública FileReCeIVETask estende o swingworker <Inteiro, objeto> {Soquete privado _msocket; public fileReCeIVETask (cliente de soquete) {this._msocket = client; } @Override Protected integer doinbackground () lança Exceção {// Obtenha meta de informação de arquivo DatainputStream input = new DatainputStream (_msocket.getInputStream ()); String filename = input.readUtf (); int fileLength = (int) input.readlong (); // número do arquivo total de bytes = novo arquivo ("c: // usuários // peixe // downloads" + file.separator + nome do arquivo); BufferoudOutputStream Output = new BufferoudOutputStream (new FileOutputStream (File)); System.out.println ("Nome do arquivo recebido =" + nome do arquivo); System.out.println ("Size de arquivo recebido =" + FILELENGLEM/1024 + "KB"); // comece a receber o conteúdo do arquivo e escrevê -los byte [] content = new Byte [2048]; int offset = 0; int numreadBytes = 0; while (deslocamento <fileLength && (numreadBytes = input.read (content))> 0) {output.Write (content, 0, numreadBytes); Precento de flutuação = 100.0f * (((float) deslocamento)/((float) comprimento do arquivo); setProgress ((int) precent); deslocamento += numreadBytes; } System.out.println ("numreadBytes =" + numreadBytes); if (deslocamento <fileLength) {numreadBytes = input.read (content); System.out.println ("numreadBytes =" + numreadBytes); System.out.println ("Erro de conteúdo do arquivo no lado do servidor"); } else {System.out.println ("A tarefa de recebimento de arquivo foi realizada corretamente"); } setProgress (100); // Diga ao cliente para fechar o soquete agora, já recebemos o arquivo com sucesso !! Bufferwriter bufferwriter = new bufferWriter (new OutputStreamWriter (_msocket.getOutputStream ())); bufferwriter.write ("done/r/n"); bufferwriter.flush (); // Fechar o arquivo e o soquete em saída.close (); _msocket.close (); retornar 100; }} Cliente:
O FileTransferClient é uma classe de interface do usuário do cliente que implementa a conexão com o servidor e depois seleciona
Arquivos a serem transferidos (imagens, PDFs, documentos do Word etc.). Se não
Digite as informações do servidor e um prompt será exibido. A porta foi especificada como: 9999
O botão [Enviar arquivo] abrirá a caixa de seleção de arquivos. Depois que o usuário selecionar o arquivo a ser transferido, crie o
FileTransferTask Thread e comece a executar a transferência de arquivos. O código da interface do usuário do cliente é o seguinte:
pacote com.gloomyfish.socket.tutorial.FileTransfer; importar java.awt.borderlayout; importar java.awt.flowlayout; importar java.awt.gridlayout; importar java.awt.event.actionEvent; importar java.awt.event.actionListener; importar java.beans.propertyChangeEvent; importar java.beans.propertyChangelistener; importar java.io.file; importar java.net.inetsocketaddress; importar java.net.socketAddress; importar javax.swing.borderFactory; importar javax.swing.boxlayout; importar javax.swing.jbutton; importar javax.swing.jfileChooser; importar javax.swing.jframe; importar javax.swing.jlabel; importar javax.swing.JOptionPane; importar javax.swing.jpanel; importar javax.swing.jProgressBar; importar javax.swing.jtextfield; /*** Normalmente escrevo comentários em inglês e, ocasionalmente, também escrevo comentários chineses, mas acho que escrever comentários em inglês* são mais unificados com o código e nada mais. */ classe pública FileTransferClient estende JFRame implementa ActionListener {/ ** * */ private estático final serialversionuid = 1L; public final Static String send_cmd = "Enviar arquivo"; public final estático int minimum = 0; public final estático int máximo = 100; // public final static string Connect_cmd = "Connect"; Privado JButton SendfileBtn; Private JTextField Serverfield; Private Jtextfield Portfield; Barra JProgressBar Private; public fileTransferClient () {super ("cliente de transferência de arquivo"); 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 (mínimo); bar.setMaximum (maximoum); jPaNELOTETTINGPANEL = JPANL; GridLayout (2,2,5,5)); ServersettingPanel.Add (Porta do servidor JLABEL ("); BtnPanel.add (sendfilebtn); public void ActionPerdEd (ActionEvent E) {String Command = E.GetActionCommand (); Chooser.SoSSO, NULL; Task.AddPropertyChangelistener (New PropertyChangelistener () {public void PropertyChange (PropertyChangeEvent EVT) {if ("Progress" .equals (Evt.getPropertyName ()) {bar.setValue (Integer) evt.getNewvalue ()); } else {// Faça nada}} public void Shows () {bar.setValue (100); / ** * Verifique se a interface do usuário já possui algumas informações de entrada corretas aqui !!! Inteiro. Client.SetSize (400, 400); As principais funções implementadas pelo FileTransferTask são:
O código -fonte completo desta classe é o seguinte:
pacote com.gloomyfish.socket.tutorial.FileTransfer; importar java.io.bufferInputStream; importar java.io.bufferedReader; importar java.io.datainputStream; importar java.io.dataOutputStream; importar java.io.file; importar java.io.fileInputStream; importar java.io.ioException; importar java.io.inputStreamReader; importar java.net.socket; importar java.net.socketAddress; importar javax.swing.swingworker; classe pública FileTransferTask estende o swingworker <Inteiro, objeto> {private arquivo selectedFile; Msocket de soquete privado; endereço de soquete privado; pai privado de filetransferclient; public fileTransferTask (arquivo de arquivo, endereço de soquete, proprietário de filetransferclient /*, jProgressBar Progress* /) {this.address = endereço; this.SelectedFile = arquivo; msocket = new Socket (); this.parent = proprietário; } @Override Protected integer doinbackground () lança exceção {// Obtenha o tamanho do arquivo comprimento longo = selectedFile.length (); if (comprimento> Integer.max_value) {lança a nova ioexception ("não conseguiu ler completamente o arquivo" + selectedFile.getName () + "como é muito longo (" + comprimento + "bytes, max suportado" + integger.max_value + ")); } msocket.connect (endereço); // Crie a matriz de bytes para manter o arquivo msocket.SetSolinger (True, 60); DataOutputStream Dout = new DataOutputStream (msocket.getOutputStream ()); // Agora começamos a enviar a meta informação do arquivo. dout.Writeutf (selectedFile.getName ()); Dout.Writelong (comprimento); Dout.flush (); // comentário final fileDatapackage pdata = new fileDatapackage (); DatainputStream é = new DataAinputStream (new FileInputStream (selecionadoFile)); byte [] bytes = novo byte [2048]; // leia nos bytes int offset = 0; int numread = 0; int fsize = (int) comprimento; while (deslocamento <fsize && (numread = is.read (bytes, 0, bytes.length))> = 0) {pdata.setData (bytes, numread); dout.Write (pdata.getpackagedata (), 0, pdata.getpackagedata (). comprimento); Dout.flush (); deslocamento += numread; Precento de flutuação = 100.0f * (((float) deslocamento)/((float) fsize); setProgress ((int) precent); } System.out.println ("Total Send Bytes =" + Offset); // Verifique se todos os bytes foram lidos em if (offset <fsize) {lança a nova ioException ("não foi possível transferir completamente o arquivo" + selectedFile.getName ()); } msocket.shutdownOutput (); // Receba a transferência de arquivo Mensagem com sucesso da conexão bufferInputStream streamReader = new BufferInputStream (msocket.getInputStream ()); BufferReader buffaredReader = new BufferredReader (new InputStreamReader (StreamReader)); String donemsg = bufferredreader.readline (); if ("feito" .equals (donemsg)) {parent.showsuccess (); } // Fechar o fluxo de entrada do arquivo setProgress (100); // Dout.close (); msocket.close (); is.close (); System.out.println ("Feche agora ..."); retornar 100; }}A aula de pacotes é a seguinte, não explicada!
pacote com.gloomyfish.socket.tutorial.FileTransfer; / ** * Este é um protocolo de transferência de arquivos muito simples sobre o soquete TCP */ classe pública Filedatapackage {private int Datalength; // o comprimento dos dados no pacote, dois bytes de byte privado [] banco de dados; // Os dados máximos no pacote, o número máximo de meici não excede 2048 bytes public final estático byte [] eof = novo byte [] {'e', 'o', 'f'}; public filedatapackage () {datalength = 0; banco de dados = novo byte [2048]; } public byte [] getPackagedata () {byte [] pdata = new Byte [Datallength]; // final de comentário system.arraycopy (banco de dados, 0, pdata, 0, comprimento de dados); retornar pdata; } public void setData (byte [] dados, int bsize) {datalength = bsize; for (int i = 0; i <databuff.length; i ++) {if (i <bsize) {databuff [i] = data [i]; } else {databuff [i] = ''; }}}}O número máximo de bytes enviados por tempo é 2048 bytes. O efeito final de execução do programa é o seguinte (Win7 + JDK6U30):
O exposto acima é tudo sobre este artigo, espero que seja útil para o aprendizado de todos.