Como implementar um Chat de mensagens para enviar arquivos via soquetes

Olá

Tenho um chat de mensagens que funciona da seguinte maneira,precisa somente de um servidor para funcionar e posso ter vários clientes para participar da lista de usuário que a mesma tem uma classe própria para gerenciamento de cliente,como seus tratamentos.

Agora queria implementar isso para enviar arquivos também.Já tenho um código pronto aqui que inicia um soquete e aguarda a classe cliente ligar para receber o arquivo.Como unir esse algoritmo ao primeiro ?

Veja isso e isso se ajuda.
Também quero fazer, então… Se conseguir, avisa k

Amigo vi tudo …valeu já tenho a minha aplicação para enviar a mensagem e também o algoritmo de enviar arquivo.

Só está dando erro quando coloco destino do arquivo no servidor .Você poderia me ajudar nisso ?

Minha classe do servidor

package servidor;
 import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
   



import servidor.Arquivo;
 
   
  public class Server {
   
           public static void main(String args[]) {
                     try {
                    	 
                    	 
                    	 
                    	 
                              //1
                              ServerSocket srvSocket = new ServerSocket(12349);
                              System.out.println("Aguardando envio de arquivo ...");
                              Socket socket = srvSocket.accept();
                              
                              //2
                              byte[] objectAsByte = new byte[socket.getReceiveBufferSize()];
                              BufferedInputStream bf = new BufferedInputStream(
                                                 socket.getInputStream());
                              bf.read(objectAsByte);
                              
                              //3
                              Arquivo arquivo = (Arquivo) getObjectFromByte(objectAsByte);
                              
                              //4
                              String dir = arquivo.getDiretorioDestino().endsWith("\") ? arquivo
                                                 .getDiretorioDestino() + arquivo.getNome() : arquivo
                                                 .getDiretorioDestino() + "/" + arquivo.getNome();
                              
                                                 
                                                 
                                                 System.out.println("Escrevendo arquivo " + dir);
   
                              //5
                              FileOutputStream fos = new FileOutputStream(dir);
                              /*FileOutputStream fos =new FileOutputStream(new File("C:\\Users\\Guilherme\\Desktop\\Área de trabalho\\rf.txt"));
                              System.out.println("Escrevendo arquivo " );*/
                                           
                              fos.write(arquivo.getConteudo());
                              fos.close();
                              
                              /*byte[] cbuffer = new byte[1024];
                  			int bytesRead;*/
                              
                             
                          /*	System.out.println("Recebendo arquivo...");
                			while ((bytesRead = is.read(cbuffer)) != -1) {
                				fos.write(cbuffer, 0, bytesRead);
                				fos.flush();
                			}*/
                			
   
                     } catch (IOException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                     }
   
           }
   
           private static Object getObjectFromByte(byte[] objectAsByte) {
                     Object obj = null;
                     ByteArrayInputStream bis = null;
                     ObjectInputStream ois = null;
                     try {
                              bis = new ByteArrayInputStream(objectAsByte);
                              ois = new ObjectInputStream(bis);
                              obj = ois.readObject();
   
                              bis.close();
                              ois.close();
   
                     } catch (IOException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                     } catch (ClassNotFoundException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();           
                     }                 
                     
                     return obj;
                     
           }
   
  }

Classe arquivo que fica no servidor

package servidor;
import java.io.Serializable;
  import java.util.Date;
   
   
  public class Arquivo implements Serializable {
   
           /**
            *
            */
           private static final long serialVersionUID = 1L;
           
           private String nome;
           private byte[] conteudo;
           private String diretorioDestino;
           private Date dataHoraUpload;        
           
           public Date getDataHoraUpload() {
                     return dataHoraUpload;
           }
           public void setDataHoraUpload(Date dataHoraUpload) {
                     this.dataHoraUpload = dataHoraUpload;
           }
           public String getNome() {
                     return nome;
           }
           public void setNome(String nome) {
                     this.nome = nome;
           }
           public byte[] getConteudo() {
                     return conteudo;
           }
           public void setConteudo(byte[] conteudo) {
                     this.conteudo = conteudo;
           }
           public String getDiretorioDestino() {
                     return diretorioDestino;
           }
           public void setDiretorioDestino(String diretorioDestino) {
                     this.diretorioDestino = diretorioDestino;
           }
  }

ClienteSockt

package Cliente;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;
   


  import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
   
  import Cliente.Arquivo;
   
  public class ClienteSocket extends javax.swing.JFrame {
           
           private long tamanhoPermitidoKB = 5120; //Igual a 5MB
           private Arquivo arquivo;
   
           
           private static final long serialVersionUID = 1L;
   
           public ClienteSocket() {
                     initComponents();
           }
   
           
      private void initComponents() {
          jLabel1 = new javax.swing.JLabel();
          jTextFieldNome = new javax.swing.JTextField();
          jButtonArquivo = new javax.swing.JButton();
          jLabelTamanho = new javax.swing.JLabel();
          jButtonEnviar = new javax.swing.JButton();
          jLabel2 = new javax.swing.JLabel();
          jTextFieldIP = new javax.swing.JTextField();
          jLabel3 = new javax.swing.JLabel();
          jTextFieldDiretorio = new javax.swing.JTextField();
          jLabel4 = new javax.swing.JLabel();
          jTextFieldPorta = new javax.swing.JTextField();
   
          setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
          jLabel1.setText("Arquivo Carregado");
   
          jTextFieldNome.setEnabled(false);
   
          jButtonArquivo.setText("Selecionar Arquivo");
          jButtonArquivo.addActionListener(new java.awt.event.ActionListener() {
              public void actionPerformed(java.awt.event.ActionEvent evt) {
                  jButtonArquivoActionPerformed(evt);
              }
          });
   
          jLabelTamanho.setFont(new java.awt.Font("Dialog", 0, 12));
          jLabelTamanho.setText("Tamanho:");
   
          jButtonEnviar.setText("Enviar");
          jButtonEnviar.addActionListener(new java.awt.event.ActionListener() {
              public void actionPerformed(java.awt.event.ActionEvent evt) {
                  jButtonEnviarActionPerformed(evt);
              }
          });
   
          jLabel2.setText("IP");
   
          jLabel3.setText("Diretorio Destino");
   
          jLabel4.setText("Porta");
   
          javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
          getContentPane().setLayout(layout);
          layout.setHorizontalGroup(
              layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
              .addGroup(layout.createSequentialGroup()
                  .addContainerGap()
                  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                      .addComponent(jTextFieldNome, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE)
                      .addComponent(jLabel1)
                      .addComponent(jButtonEnviar)
                      .addComponent(jButtonArquivo)
                      .addComponent(jLabelTamanho)
                      .addGroup(layout.createSequentialGroup()
                          .addComponent(jLabel2)
                          .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 104, Short.MAX_VALUE)
                          .addComponent(jTextFieldIP, javax.swing.GroupLayout.PREFERRED_SIZE, 162, javax.swing.GroupLayout.PREFERRED_SIZE))
                      .addGroup(layout.createSequentialGroup()
                          .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                              .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                  .addComponent(jLabel4)
                                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                  .addComponent(jTextFieldPorta, javax.swing.GroupLayout.PREFERRED_SIZE, 162, javax.swing.GroupLayout.PREFERRED_SIZE))
                              .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                  .addComponent(jLabel3)
                                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                  .addComponent(jTextFieldDiretorio, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)))
                          .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 2, javax.swing.GroupLayout.PREFERRED_SIZE)))
                  .addGap(37, 37, 37))
          );
          layout.setVerticalGroup(
              layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
              .addGroup(layout.createSequentialGroup()
                  .addContainerGap()
                  .addComponent(jLabel1)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addComponent(jTextFieldNome, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                      .addComponent(jLabel2)
                      .addComponent(jTextFieldIP, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                      .addComponent(jLabel4)
                      .addComponent(jTextFieldPorta, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                      .addComponent(jLabel3)
                      .addComponent(jTextFieldDiretorio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                  .addGap(16, 16, 16)
                  .addComponent(jButtonArquivo)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addComponent(jLabelTamanho)
                  .addGap(25, 25, 25)
                  .addComponent(jButtonEnviar)
                  .addGap(139, 139, 139))
          );
          pack();
      }// </editor-fold>//GEN-END:initComponents
      private void jButtonEnviarActionPerformed(java.awt.event.ActionEvent evt) {
          enviarArquivoServidor();
}      

       private void jButtonArquivoActionPerformed(java.awt.event.ActionEvent evt) {
          FileInputStream fis;
          try {
                   
                   JFileChooser chooser = new JFileChooser();
                   chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
                   chooser.setDialogTitle("Escolha o arquivo");
                   
                   if (chooser.showOpenDialog(this) == JFileChooser.OPEN_DIALOG) {
                             File fileSelected = chooser.getSelectedFile();
                             
                             byte[] bFile = new byte[(int) fileSelected.length()];
                             fis = new FileInputStream(fileSelected);
                             fis.read(bFile);
                             fis.close();
                             
                             long kbSize = fileSelected.length() / 1024;
                             jTextFieldNome.setText(fileSelected.getName());
                             jLabelTamanho.setText(kbSize + " KB");
                             //aqui começa atual o arquivo
                             arquivo = new Arquivo();
                             arquivo.setConteudo(bFile);
                             arquivo.setDataHoraUpload(new Date());
                             arquivo.setNome(fileSelected.getName());
                             arquivo.setTamanhoKB(kbSize);
                             arquivo.setIpDestino(jTextFieldIP.getText());
                             arquivo.setPortaDestino(jTextFieldPorta.getText());
                            arquivo.setDiretorioDestino(jTextFieldDiretorio.getText().trim());
                   }
                   
          } catch (Exception e) {
                   e.printStackTrace();
          }
}
private void enviarArquivoServidor(){
    if (validaArquivo()){
             try {
                       Socket socket = new Socket(jTextFieldIP.getText().trim(),
                                         Integer.parseInt(jTextFieldPorta.getText().trim()));
                       
                       BufferedOutputStream bf = new BufferedOutputStream(socket.getOutputStream());
                       
                       byte[] bytea = serializarArquivo();
                       bf.write(bytea);
                       bf.flush();
                      bf.close();
                       socket.close();
             } catch (UnknownHostException e) {
                       e.printStackTrace();
             } catch (IOException e) {
                       e.printStackTrace();
             }
    }
}

private byte[] serializarArquivo(){
    try {
             ByteArrayOutputStream bao = new ByteArrayOutputStream();
             ObjectOutputStream ous;
             ous = new ObjectOutputStream(bao);
             ous.writeObject(arquivo);
             return bao.toByteArray();
    } catch (IOException e) {
             e.printStackTrace();
    }

    return null;
}

private boolean validaArquivo(){
    if (arquivo.getTamanhoKB() > tamanhoPermitidoKB){
             JOptionPane.showMessageDialog(this,
                                "Tamanho máximo permitido atingido ("+(tamanhoPermitidoKB/1024)+")");
             return false;
    }else{
             return true;
    }
}


public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {
             public void run() {
                       new ClienteSocket().setVisible(true);
             }
    });
}

private javax.swing.JButton jButtonArquivo;
private javax.swing.JButton jButtonEnviar;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabelTamanho;
private javax.swing.JTextField jTextFieldDiretorio;
private javax.swing.JTextField jTextFieldIP;
private javax.swing.JTextField jTextFieldNome;
private javax.swing.JTextField jTextFieldPorta;
}

E a classe Arquivo do Cliente

package Cliente;
import java.io.Serializable;
  import java.util.Date;
   
  public class Arquivo implements Serializable {
   
           /**
            *
            */
           private static final long serialVersionUID = 1L;
                     
           private String nome;
           private byte[] conteudo;
           private transient long tamanhoKB;
           private transient Date dataHoraUpload;
           private transient String ipDestino;
           private transient String portaDestino;
           private String diretorioDestino;
           public String getNome() {
                     return nome;
           }
           public void setNome(String nome) {
                     this.nome = nome;
           }
           public byte[] getConteudo() {
                     return conteudo;
           }
           public void setConteudo(byte[] conteudo) {
                     this.conteudo = conteudo;
           }
           public long getTamanhoKB() {
                     return tamanhoKB;
           }
           public void setTamanhoKB(long tamanhoKB) {
                     this.tamanhoKB = tamanhoKB;
           }
           public Date getDataHoraUpload() {
                     return dataHoraUpload;
           }
           public void setDataHoraUpload(Date dataHoraUpload) {
                     this.dataHoraUpload = dataHoraUpload;
           }
           public String getIpDestino() {
                     return ipDestino;
           }
           public void setIpDestino(String ipDestino) {
                     this.ipDestino = ipDestino;
           }
           public String getPortaDestino() {
                     return portaDestino;
           }
           public void setPortaDestino(String portaDestino) {
                     this.portaDestino = portaDestino;
           }
           public String getDiretorioDestino() {
                     return diretorioDestino;
           }
           public void setDiretorioDestino(String diretorioDestino) {
                     this.diretorioDestino = diretorioDestino;
           }
  }

O servidor está rodando e fica só aguardando o cliente chamar.

Porém quando eu coloco o destinho no textfield da erro e não executa.Minha duvida é ,será que estou colocando o destinho de forma certa?

Nesse bloco deu erro ao deixar a barra \

Então coloquei assim /

   String dir = arquivo.getDiretorioDestino().endsWith("/") ? arquivo
                                                 .getDiretorioDestino() + arquivo.getNome() : arquivo
                                                 .getDiretorioDestino() + "/" + arquivo.getNome();
                              
                                                 
                                                 
                                                 System.out.println("Escrevendo arquivo " + dir);

O Destino C:\Users\Guilherme\Documents

Erro

java.lang.ClassNotFoundException: Cliente.Arquivo
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at java.io.ObjectInputStream.resolveClass(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at servidor.Server.getObjectFromByte(Server.java:82)
at servidor.Server.main(Server.java:38)
Exception in thread “main” java.lang.NullPointerException
at servidor.Server.main(Server.java:41)

Linha 41 do server é

String dir = arquivo.getDiretorioDestino().endsWith("/") ? arquivo