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
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 ?