Duvida socket . ! Resolvido

Galera tenho um Cliente em Swing que no onclick do botão executa o seguinte:

public class Cliente extends JFrame {

ClienteSocket clienteSocket = null;

Abaixo o onclick do botão


log.append("Iniciando processo de transferência de arquivo ...\n");
							log.append("Conectando ao servidor ["+ipServidor.getText()+"] ...\n");							
							
							clienteSocket = new ClienteSocket(arquivo.getText(),cliente , falhas.getSelectedIndex() );
							//Inicializa Servidor
							clienteSocket.inicializa();	

O problema é que se inicio meu servidor e mando enviar o arquivo ele envia bem direitinho, mas se nao fechou meu cliente e inicio meu servidor de novo e clico no botao para enviar o arquivo ele nao envia, da pau :frowning:

Erro:

java.net.SocketException: Connection reset
	at java.net.SocketInputStream.read(SocketInputStream.java:168)
	at java.net.SocketInputStream.read(SocketInputStream.java:182)
	at java.io.DataInputStream.readLine(DataInputStream.java:473)
	at cliente.ClienteSocket.inicializa(ClienteSocket.java:209)
	at view.Cliente$1.actionPerformed(Cliente.java:196)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1849)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2169)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
	at java.awt.Component.processMouseEvent(Component.java:5488)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3126)
	at java.awt.Component.processEvent(Component.java:5253)
	at java.awt.Container.processEvent(Container.java:1966)
	at java.awt.Component.dispatchEventImpl(Component.java:3955)
	at java.awt.Container.dispatchEventImpl(Container.java:2024)
	at java.awt.Component.dispatchEvent(Component.java:3803)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4212)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3892)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3822)
	at java.awt.Container.dispatchEventImpl(Container.java:2010)
	at java.awt.Window.dispatchEventImpl(Window.java:1778)
	at java.awt.Component.dispatchEvent(Component.java:3803)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)

Aqui o código completo do ClienteSocket responsável por enviar a mensagem para o servidor:

package cliente;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.zip.CRC32;

import util.Checksum32;
import util.Util;
import view.Cliente;

public class ClienteSocket {
	
	Socket socket = null; // Scocket para conexão

	FileInputStream in = null; //Stream para o nosso arquivo
	
	File arquivo = null; // O arquivo :)
	
	Cliente cliente; //Nossa tela gráfica onde imprimiremos o resultado
	
	Util util = new Util(); //Classe com métodos para retornar alguns valores necessários
	
	CRC32 crc32 = new CRC32(); //Declara nossa classe que calcula o CRC
	
	DataInputStream inputServer = null; // Duto para receber dados do servidor
	
	boolean enviando = true //Verifica se está enviando ou se terminou
	, falhaEnvio = false // Verifica se houve falha no envio 
	, ultimoEnvio = false  //Verifica se é o último envio
	, falhas=false; // Váriável que diz se o usuário selecionou ou não com falhas.
	
	int qtdeEnvio=0; //Verifica quantas vezes já foi enviado

	/**
	 * Construtor da classe
	 */
	public ClienteSocket(String pathNomeArquivo, Cliente cliente , int falhas) {

		//Referencia a nossa Janela (JFrame) para imprimir os logs nela
		this.cliente = cliente;
		// Seta o arquivo que será transferido
		arquivo = new File(pathNomeArquivo);
		//Verifica se terá falhas
		if( falhas == 2 )
			this.falhas=true;		
	}

	/**
	 * Inicializa a transferência do arquivo
	 *
	 */
	public void inicializa() {

		try {
			
			//Abrimos um FileInputStream para o arquivo
			in = new FileInputStream(arquivo.getAbsolutePath());
			
			try {
				
				//Criação so socket
				socket = new Socket("127.0.0.1", 4001);				
				
				//Log do cliente
				
				escreveCliente("Conectado ...\n");
				
				//Duto para receber dados do servidor
				inputServer = new DataInputStream(socket.getInputStream());
				
			} catch (Exception e) {
				//Caso o servidor não tenha sido iniciado
				limpaLog();
				escreveCliente("Falha ao conectar ao Servidor!\n");				
			}
			
			//Seta o tamanho máximo do quadro
			util.setTamanhoMaximo( new Integer(cliente.getTamanhoJanelaText()).longValue() );
			
			//Logs do cliente
			escreveCliente("Tamanho do arquivo é ["+util.tamanhoDoArquivo(new FileInputStream(arquivo.getAbsolutePath()))+" bytes] ...\n" );
			escreveCliente("O Arquivo pode ser quebrado em "+util.calculaPartesArquivo()+" partes  ...\n");
			escreveCliente("Transferindo Arquivo ... ["+arquivo.getAbsolutePath()+"] em "+util.getNumPartes()+" Etapas ...\n");

			//Pega o stream para gravar no servidor
			OutputStream outFile = socket.getOutputStream();

			while(enviando) {

				//Se houve falha no envio
				if( falhaEnvio ) {
					
					//Logs do cliente
					//escreveCliente("Falha no envio ...\n");
					escreveCliente("Reenviando pacotes ...\n");

					//Lê o arquivo novamente
					in = new FileInputStream(arquivo.getAbsolutePath());

					//Logs do cliente
					/*escreveCliente("Tamanho do arquivo é ["+util.tamanhoDoArquivo(new FileInputStream(arquivo.getAbsolutePath()))+" bytes] ...\n" );
					escreveCliente("O Arquivo pode ser quebrado em "+util.calculaPartesArquivo()+" partes  ...\n");
					escreveCliente("Retransferindo Arquivo ... ["+arquivo.getAbsolutePath()+"] em "+util.getNumPartes()+" Etapas ...\n");*/
				}

				//Se a quantidade de tentativas ultrapassar 3, termina.
				if( qtdeEnvio==3 ) {
					
					//Log do cliente
					escreveCliente("Falha ao enviar arquivos!");
					//Termina de enviar
					enviando=false;
					//Sai do laço
					break;
				}
			
			//Faz alguns calculos para verificar e ordenar o envio
			//por partes, de forma que ele envie do byte 0 de X em X vezes, sendo X o tamanho
			//da janela definido pelo usuário, até que chegue ao final do arquivo.
			for( int i = 1 ;  i <= util.getNumPartes() ; i++)   {			  					   
				 // Se  for a primeira Etapa e sobrou true
				 if( i==1 && i<=util.getNumPartes() ) {						 
					 if (util.getTamanhoArquivo() >= util.getTamanhoMaximo())
						 util.setFim( (int) util.getTamanhoMaximo() );
			         else
			       	     util.setFim((int)util.getTamanhoArquivo() );						 
				 }
				 //Se não for a primeira Etapa e sobrou false
				 if( i>1 && i<util.getNumPartes() ) {						
					 util.setInicio( util.getInicio() + (int) util.getTamanhoMaximo() );
					 util.setFim( util.getFim() + (int) util.getTamanhoMaximo()  );
				 } 
				 //Se não for a primeira Etapa e sobrou true
				 else if( i>1 && i==util.getNumPartes() && util.isSobrou() ) {						 
					 util.setInicio( util.getInicio() + (int) util.getTamanhoMaximo()  );
					 util.setTamanhoMaximo(util.getTamanhoArquivo() % util.getTamanhoMaximo());
					 util.setFim( (int)util.getTamanhoArquivo() );
				}
				 
				 //Verifica se é o último pacote a enviar
				 if( i == util.getNumPartes() )
					 ultimoEnvio=true;
				 
				 //Log do cliente 
				 escreveCliente("Transferindo Inicio: " + util.getInicio() + " bytes Fim: "+util.getFim()+" bytes \n");
				 
				// Neste momento ele define o array de bytes com o tamanho
			    //especificado pelo usuário. Este array é temporário pois ainda precisamos
				//acrescentar o checksum								
				byte[] bytesTemp = new byte[(int)util.getTamanhoMaximo()];
				
				//Aqui ele lê esses bytes. Exemplo: Se o usuário definiu 50 bytes (O máximo)
				//ele irá ler os 50 primeiros bytes, depois mais 50(Sem ler os primeiros 
				//de novo por que ele usa um buffer interno) até acabar de ler todas as posições
				//Inclusive caso sobre no ultimo pacote e as quantidades não fiquem as mesmas
				//na última leitura a variável tamanho máximo tera o valor do resto que sobrou
				//não ficando nosso arquivos com espaços em branco :)				
				in.read(bytesTemp);
				
				//Instancia a classe que faz o calculo do checksum
				Checksum32 cis2 = new Checksum32();
				//Armazena o retorno do checkSum
				long checksum = cis2.calculaCheckSum(bytesTemp, (int)util.getTamanhoMaximo() ) ;
				//Transforna em String
				String binarioCRC32 = new String( new Long(checksum).toString() );				
				//Pega o array de bytes desde calculo				
				byte[] checkSum = String.valueOf(binarioCRC32).getBytes();
				
				//Aqui sim nós começamos a montar nosso array que irá ser enviado para o servidor.
				//Como funciona: Ele pega o total de bytes do arquivo que sabemos que vamos enviar,
				//mais o total de bytes do checksum mais 2 posições que são as que armazenam
				//a quantidade de bytes que vamos ler para dados e checksum
				byte[] bytes = new byte[(int)util.getTamanhoMaximo()+checkSum.length+2];
				
				//Armazena primeiramente a quantidade que vai ser lida de dados e checksum e log após
				//os bytes do arquivo
				for ( int g = 0 ; g < bytesTemp.length ; g++ ) {				
					if( g == 0 ) {
						bytes[g] = (byte)util.getTamanhoMaximo(); //Quantidade de byte dados que será lida no servidor				
						bytes[g+1] = (byte)checkSum.length; //Quantidade de byte checksum que será lida no servidor
						bytes[g+2] = bytesTemp[g]; //Já armazena o primeiro dado na próxima posição
					}
					else
						bytes[g+2] = bytesTemp[g]; //Armazena o restante dos dados				
				}
				
				//Variável que armazena a próxima posição do nosso array de bytes que contém
				//a quantidade de bytes que temos que ler de dados e checksum e também os próprios dados
				int proxPos = bytesTemp.length+2;				
				//Armazena ao final dos bytes o código checksum
				for ( int g = 0 ; g < checkSum.length ; g++ ) {
					//Verifica se o usuário optou por forçar falhas ou não
					if(!falhas)
						bytes[proxPos] = checkSum[g]; //Sem falhas
					else
						bytes[proxPos] = (byte)Math.random(); //Com falhas
					proxPos++; //Incrementa posição
				}
				
				//Estando o array pronto com o tamanho de dados e checksum que temos que ler e dependendo do tamanho
				//de pacotes que foi quebrado, cada leva de dados de arquivos é de no máximo 50 bytes
				//Envia os bytes lidos ao servidor
				outFile.write(bytes);
				
				//Recebe a reposta se o envio foi OK ou Falhou
				String resposta = inputServer.readLine();
				
				//Verifica a resposta, se falhou manda tudo de novo.
				if( resposta.equalsIgnoreCase("false")  ) {
					escreveCliente("Ocorreu uma falha ao enviar o pacote " + i + " ... \n");
					falhaEnvio=true;
					qtdeEnvio++;
					break;
				}
				else
					escreveCliente("Pacote [ " + i + " ] enviado com sucesso ...\n");							
			}		
			
			//Se não falhou e não tem mais pacotes para enviar. Acaba!
			if( (!falhaEnvio) && (ultimoEnvio) )
				enviando=false;			
		}
			
			//Se não houve falha no envio
			if(!falhaEnvio)			
				escreveCliente("\nArquivo transferido com sucesso.\n"); //Log do cliente
			
			in.close(); //Fecha o arquivo
			socket.close(); //Fecha o Socket			
			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	/**
	 * Escreve os logs no cliente
	 *
	 */
	public void escreveCliente(String log) {
		cliente.setLog(log);		
	}
	
	/**
	 * Limpa o Log
	 *
	 */
	public void limpaLog() {
		cliente.limpaLog();		
	}

}

Abaixo segue o codigo do ServerSockjet responsavel por receber o arquivo:

package servidor;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.FileChannel;

import util.Checksum32;
import view.Servidor;

public class ServidorSocket {

	private ServerSocket serskt = null; // Socket para conexão
	
	private Socket listen = null; //Nosso Socket :)
	
	private BufferedReader in = null; //Buffered para leitura

	private OutputStream out = null; // Stream para o arquivo

	private FileOutputStream fout = null; // FileOutputStream para o arquivo

	private Servidor servidor; // Nossa tela gráfica do servidor para enviarmos mensagens

	private PrintStream outPutClient = null; // Duto para enviar dados ao cliente

	private boolean servidorOnOff = true, // Verifica se o servidor espera por pacotes ou encerra
	ocorreuErro = false; // Verifica se ocorreu algum erro

	private int nroArquivo = 1; // Incrementa a cada envio de um novo arquivo para que eles não tenham o mesmo nome ao serem salvos

	/**
	 * Construtor da Classe
	 */
	public ServidorSocket(Servidor serv) {
		this.servidor = serv;

	}

	/**
	 * Inicializa o servidor
	 * @throws IOException 
	 */
	public void inicializarServidor() throws IOException {

		try {
			// Pega o diretório atual
			String local = System.getProperty("user.dir");
			// Pega o nome do pacote desta classe
			String pacote = this.getClass().getPackage().getName();
			// Monta o nome do arquivo Temporário
			String nomeArqTempServer = local + "/" + pacote + "/TempServer.txt";

			try {

				// Cria o servidor na porta especificada
				serskt = new ServerSocket(4001);

			} catch (Exception e) {
				e.printStackTrace();
			}
			
			// Cria o FileOutputStream para o arquivo
			fout = new FileOutputStream(nomeArqTempServer);

			try {
				// Aguarda uma conexão
				listen = serskt.accept();

				// Enquanto não mandar terminar o servidor
				while (servidorOnOff) {

					// Se ocorreu algum erro no envio
					if (ocorreuErro) {
						escreveServidor("Algum erro ocorreu com o envio de pacotes ...\n");
						escreveServidor("Aguardando reenvio de pacotes ...\n");
					}

					// Duto para enviar dados ao cliente
					outPutClient = new PrintStream(listen.getOutputStream());

					// Log do servidor
					escreveServidor("Uma Conexão foi estabelecida pelo host "
							+ listen.getInetAddress() + " ...\n");
					if (ocorreuErro)
						escreveServidor("Pacotes sendo reenviados ...\n");

					// Cria um buffer para leitura do arquivo recebido
					in = new BufferedReader(
							new InputStreamReader(listen.getInputStream(),
									"ISO-8859-1"));

					// Stream com Buffer para o arquivo
					out = new BufferedOutputStream(fout);

					// Log do servidor
					escreveServidor("Transferindo arquivo ...\n");

					// Aqui criamos os dois array de bytes. O primeiro
					// responsável por armazenar os dados recebidos
					// e o segundo responsável por armazenar os calculos de
					// checksum do cliente
					byte[] bytesRecebidos = null;
					byte[] bytesCheckSum = null;

					// Contador para ver qual pacote está sendo lido
					int verificador = 0;
					// Contador para armazenar o numero de dados referente ao
					// arquivo que serão lidos
					int nroBytesBinario = 0;
					// Contador para armazenar o numero de dados referente 
					// ao Checksum que será lidos
					int nroBytesCheckSum = 0;

					// Enquanto recebe dados, salva em um array de bytes,
					// verifica o checksum e guarda para criar arquivo
					try {
						while (true) {
							int data = in.read(); // Recebe os dados do cliente

							if (data == -1) { // Se retornar -1 acabou
								servidorOnOff = false;
								break;
							}

							// As duas primeiras posições só queremos saber a
							// quantidade de bytes que vamos ler para dados e
							// checksum
							if (verificador <= 1) {
								// Caso for a primeira posição, no caso é a
								// posição que retorna quantos bytes de dados
								// ele terá que ler para o primeiro pacote.
								if (verificador == 0) {
									// Armazena na variável para saber quantos
									// bytes terá que ler de dados
									nroBytesBinario = data;
								}
								// Caso for a segunda posição, no caso é a
								// posição que retorna quantos bytes de checksum
								// ele terá que ler para o primeiro pacote.
								else {
									// Armazena na variável para saber quantos
									// bytes terá que ler para o checksum
									nroBytesCheckSum = data;
									// Cria o array de bytes com o tamanho que
									// irá ler dos dados do arquivo
									bytesRecebidos = new byte[nroBytesBinario];
									// Cria o array de bytes com o tamanho que
									// irá ler do checksum
									bytesCheckSum = new byte[nroBytesCheckSum];
								}
								// Incrementa o verificador para não cair mais
								// nesta condição até que leia todas as posições
								// indicadas
								verificador++;
							}
							// Aqui ele começa a armazenar os dados até que o
							// número de posições lidas bata com o número
							// de posições que ele tem que ler. O qual foi
							// recebido anteriormente.
							else {
								// Primeiro armazenamos os dados
								for (int i = 0; i < nroBytesBinario; i++) {
									bytesRecebidos[i] = (byte) data;
									data = in.read();
								}
								// Agora armazenamos o checksum
								for (int i = 0; i < nroBytesCheckSum; i++) {
									bytesCheckSum[i] = (byte) data;
									// Caso for a ultima posição a ler não
									// recebe novo dado, pois o próximo dado
									// será lido no primeiro trecho deste while
									// novamente e será o próximo número de
									// posições a serem lidas
									if (!(i + 1 == nroBytesCheckSum))
										data = in.read();
								}
								// Verificador recebe zero novamente para que
								// caia na condição de armazenar um novo número
								// de posições a serem lidas
								verificador = 0;

								// Instancia a classe que faz o calculo do
								// checksum
								Checksum32 cs32 = new Checksum32();
								// Armazena o retorno do checkSum
								long checksum = cs32.calculaCheckSum(
										bytesRecebidos, bytesRecebidos.length);
								// Transforna em String
								String crc32Servidor = new String(new Long(
										checksum).toString());
								// Pega o CheckSum que o Cliente Gerou
								String crc32Cliente = new String(bytesCheckSum,
										0, bytesCheckSum.length);
								// Compara os checkSum para verificar se houve
								// algum erro na transmissão
								if (crc32Servidor.trim().equalsIgnoreCase(
										crc32Cliente.trim())) {
									escreveServidor("Cálculo de Checksum ... OK!\n");
									// Grava os dados no arquivo
									out.write(bytesRecebidos);
									// Manda para o cliente dizendo que o envio
									// foi ok
									outPutClient.println("true");
								} else {
									escreveServidor("Cálculo de Checksum ... FALHOU!\n");
									ocorreuErro = true;
									// Manda para o cliente dizendo que o envio
									// falhou
									outPutClient.println("false");
									// Para a execução pois houve erro em algum
									// pacote
									break;
								}
							}
						}
					} finally {
						if (out != null) {
							out.close();
						}
					}

					// Se não ocorreu erro grava os dados do pacote no arquivo
					if (!ocorreuErro) {

						// Pega o arquivo temporario
						FileChannel from = new RandomAccessFile(nomeArqTempServer,"r").getChannel();
						
						// Caso já exista um arquivo com este nome ele troca a variável para
						// criar um arquivo com outro nome 
						while( true ) {
							File arquivo = new File(local+"/"+pacote+"/Arquivo"+nroArquivo+".txt");
							if( !arquivo.exists() )
								break;
							else
								nroArquivo++;
						}
						
						// Cria um novo arquivo
						FileChannel to = new RandomAccessFile(local+"/"+pacote+"/Arquivo"+nroArquivo+".txt","rw").getChannel();
						// Aqui ele faz uma cópia do arquivo temporário do
						// servidor
						// para o arquivo que realmente será visualizado
						from.transferTo(0, from.size(), to);
						// Incrementa para que o proximo arquivo não tenha o
						// mesmo nome
						nroArquivo++;

						// Fecha os canais de copia
						from.close();
						to.close();

						// Log do servidor
						escreveServidor("Arquivo transferido ...\n");
					}
					else
						//Log do servidor
						escreveServidor("Falha ao transferir arquivo ...\n");
				}

			} catch (IOException e) {
			}
			// limpaLogServidor();
			escreveServidor("A Conexão foi encerrada ...\n");		
			//Deleta o arquivo temporário do servidor
			File file = new File(nomeArqTempServer);
			if(file.exists())
				file.delete();			

		}
		catch (Exception e) {			
			e.printStackTrace();
		}
		finally{
			
			if (in != null) {
				in.close();
			}			
			if (listen != null) {
				listen.close();
			}
			
			servidor = null;
			
		}

	}
	
	/**
	 * Escreve os logs no servidor
	 */
	public void escreveServidor(String log) {
		servidor.setLog( log );		
	}

	/**
	 * Limpa o Log do servidor
	 */
	public void limpaLogServidor() {
		servidor.limpaLog();
	}
}

Caso alguém ainda saiba me dizer com todos esses processos que tenhoq ue fazer, tem como ainda eu deixar o meu servidor em loop para receber outros arquivos ?