Estou desenvolvendo uma aplicação cliente-servidor em que o servidor é uma videoteca digital. O cliente pode se conectar ao servidor e requisitar um arquivo de vídeo específico, a lista geral de arquivos de vídeo armazenados no servidor, e pode enviar vídeos para o servidor armazenar…Desenvolvi um protocolo de aplicação sobre o qual o cliente e o servidor comunicam suas intenções. As mensagens trafegam na rede em Objetos do tipo Mensagem…Todavia, meu servidor está apresentando um problema na leitura deste tipo de objeto (ele lê o primeiro, todavia quando fica esperando o próximo dá problema). Vou enviar o código das classes envolvidas (omitindo os imports afim de poupar espaço):
Código do servidor:
public class Servidor extends Thread
{
private ServerSocket servidor;
private Vector<Conexao> conexoes;
private Controlador controlador;
public Servidor(Controlador controlador)throws IOException
{
this.controlador = controlador;
this.servidor = new ServerSocket(controlador.getportaDoServidor());
this.conexoes = new Vector();
System.out.println("Iniciando Servidor...");
this.start();
}
public void run()
{
while (true)
{
try
{
Socket cliente = servidor.accept();
System.out.println("Conectou...");
Conexao conexao = new Conexao(cliente,this);
}
catch(Exception E)
{
//controlador.insereAviso("Problemas..."+E+"");
System.out.println("Problemas..."+E+"");
E.printStackTrace();
}
}
}
public boolean usuarioTemAcesso(String identificacao)
{
if(identificacao.equals("#$%Joel*Luis*Carbonera%$#"))
{
return true;
}
return false;
}
public synchronized void persisteConexao(Conexao conexao)
{
conexoes.add(conexao);
}
public Controlador getControlador()
{
return controlador;
}
public static void main(String args[])
{
try
{
Servidor servidor = new Servidor(new Controlador());
}
catch(Exception e)
{
System.out.println("Erro: " + e);
e.printStackTrace();
}
}
}
Código da Conexao
public class Conexao extends Thread
{
private ObjectInputStream entradaObjeto;
private ObjectOutputStream saidaObjeto;
private DataInputStream entradaDado;
private DataOutputStream saidaDado;
private Socket cliente;
private String IDDoClienteConectado;
public boolean continua = true;
private Servidor servidor;
/*-"conexoesDoServidor" eh uma referencia ao objeto Vector do Servidor que guarda as conexoes ativas
*-"controlador" � a camada entre o processamento e a apresentacao
*/
public Conexao(Socket cliente, Servidor servidor) throws IOException
{
this.cliente = cliente;
this.servidor = servidor;
//Obtendo os fluxos de entrada e saida a partir do socket
this.entradaObjeto = new ObjectInputStream(this.cliente.getInputStream());
this.saidaObjeto = new ObjectOutputStream(this.cliente.getOutputStream());
this.saidaDado = new DataOutputStream(this.cliente.getOutputStream());
this.entradaDado = new DataInputStream(this.cliente.getInputStream());
try
{
Mensagem<String> requisicao = (Mensagem<String>)entradaObjeto.readObject();
System.out.println("Identidade recebida");
Mensagem resposta;
if(servidor.usuarioTemAcesso( requisicao.getDados() ))
{
resposta = new Mensagem(TipoDeMensagem.RESPOSTA_IDENTIDADE_CONFIRMADA);
saidaObjeto.writeObject(resposta);
saidaObjeto.flush();
servidor.persisteConexao(this);
System.out.println("Identidade confirmada");
start();
}
else
{
resposta = new Mensagem(TipoDeMensagem.RESPOSTA_IDENTIDADE_NAO_CONFIRMADA);
saidaObjeto.writeObject(resposta);
saidaObjeto.flush();
System.out.println("Identidade não confirmada");
entradaObjeto.close();
saidaObjeto.close();
cliente.close();
}
}
catch(IOException IOE)
{
//System.out.println("Erro de I/O...Voc� na precisa saber exatamente qual erro...");
IOE.printStackTrace();;
}
catch(ClassNotFoundException CNFE)
{
System.out.println("Erro inesperado...Se voc� conseguiu gerar esse erro, parab�ns...");
CNFE.printStackTrace();
}
}
public String getIDDoCliente()
{
return IDDoClienteConectado;
}
//o cliente nao atualiza a propria msg e o servidor nao faz o controle daquele que enviou para que nao recebe a propria msg que enviou
public void run()
{
System.out.println("Está conectado "+cliente.isConnected()+"");
TipoDeMensagem tipo;
while(continua)
{
try
{
Mensagem mensagem = (Mensagem)entradaObjeto.readObject();
tipo = mensagem.getTipoDeMensagem();
if(tipo==TipoDeMensagem.REQUISICAO_ENVIO_DE_ARQUIVO_DE_VIDEO)
{
//Cliente pede que servidor envie arquivo
System.out.println("Requisição para envio de arquivo recebida");
System.out.println("Arquivo "+mensagem.getDados()+"");
enviaDadosDoVideo((String)mensagem.getDados());
}
else if(tipo==TipoDeMensagem.REQUISICAO_RECEBIMENTO_DE_ARQUIVO_DE_VIDEO)
{
}
Thread.sleep(100);
}
catch(IOException IOE)
{
System.out.println(IOE);
IOE.printStackTrace();
}
catch(ClassNotFoundException CNFE)
{
System.out.println(CNFE);
CNFE.printStackTrace();
}
catch(InterruptedException IE)
{
System.out.println(IE);
IE.printStackTrace();
}
catch(Exception ex)
{
System.out.println(ex);
ex.printStackTrace();
}
}
try
{
entradaObjeto.close();
saidaObjeto.close();
cliente.close();
}
catch(IOException IOE)
{
System.out.println("Ocorreu um erro de I/O inesperado ");
}
}
public void recebeDadosDoVideo(String nomeDoVideo)throws IOException, ClassNotFoundException
{
}
//Talvez tenha que colocar isto dentro de uma thread para não travar a audição do cliente
public void enviaDadosDoVideo(String nomeDoArquivo)throws Exception
{
File arquivoAEnviar = (servidor.getControlador()).getArquivoDeVideo(nomeDoArquivo);
System.out.println("Enviando arquivo "+arquivoAEnviar.getPath()+"");
Mensagem mensagem = new Mensagem(TipoDeMensagem.TRANSPORTE_INFORMACAO_DE_TAMANHO_DE_ARQUIVO,new Integer((int)arquivoAEnviar.length()));
System.out.println(mensagem);
saidaObjeto.writeObject(mensagem);
saidaObjeto.flush();
DataInputStream entradaArquivo = new DataInputStream(new FileInputStream(arquivoAEnviar));
int bytesParaEnviar = entradaArquivo.available();
int tamanhoDoFragmento = 1024;
byte[] dados = new byte[tamanhoDoFragmento];
int bytesEscritos;
while(bytesParaEnviar>0)
{
bytesEscritos = (bytesParaEnviar >= tamanhoDoFragmento ? tamanhoDoFragmento : bytesParaEnviar);
System.out.println("Falta enviar "+bytesParaEnviar+" bytes");
entradaArquivo.read(dados,0,bytesEscritos);
saidaDado.write(dados,0,bytesEscritos);
bytesParaEnviar = bytesParaEnviar - bytesEscritos;
try
{
Thread.sleep(0,5);
}
catch(InterruptedException IE)
{
continue;
}
}
entradaArquivo.close();
}
public void enviaListaDeVideos()throws ExcecaoDeRede
{
try
{
Vector<String> lista = (servidor.getControlador()).getListaDeNomesDeVideos();
Mensagem<Vector<String>> mensagem = new Mensagem(TipoDeMensagem.TRANSPORTE_LISTA_DE_VIDEOS,lista);
this.saidaObjeto.writeObject(mensagem);
this.saidaObjeto.flush();
}
catch(IOException IOE)
{
throw new ExcecaoDeRede();
}
}
public void desconecta()
{
}
}
Código do Cliente:
public class Cliente
{
private Socket socket;
private ObjectOutputStream saidaObjeto;
private ObjectInputStream entradaObjeto;
private DataInputStream entradaDado;
private DataOutputStream saidaDado;
private String identificacao;
private boolean estahConectado;
private Controlador controlador;
public Cliente(String identificacao,Controlador controlador)throws ExcecaoDeIdentidadeNaoConfirmada, ExcecaoDeRede
{
this.identificacao = identificacao;
this.controlador = controlador;
this.conecta();
}
public void conecta()throws ExcecaoDeIdentidadeNaoConfirmada, ExcecaoDeRede
{
try
{
this.socket = new Socket(controlador.getIPServidor(),controlador.getPortaServidor());
this.saidaObjeto = new ObjectOutputStream(socket.getOutputStream());
this.entradaObjeto = new ObjectInputStream(socket.getInputStream());
this.saidaDado = new DataOutputStream(socket.getOutputStream());
this.entradaDado = new DataInputStream(socket.getInputStream());
Mensagem<String> ID = new Mensagem(TipoDeMensagem.REQUISICAO_DE_CONFIRMACAO_DE_IDENTIDADE,identificacao);
saidaObjeto.writeObject(ID);
saidaObjeto.flush();
System.out.println("Enviada a identidade, aguardando resposta");
Mensagem resposta = (Mensagem)entradaObjeto.readObject();
System.out.println("Resposta recebida");
if(resposta.getTipoDeMensagem()==TipoDeMensagem.RESPOSTA_IDENTIDADE_CONFIRMADA)
{
System.out.println("Identidade confirmada");
this.estahConectado = true;
}
else
{
System.out.println("Identidade não confirmada");
throw new ExcecaoDeIdentidadeNaoConfirmada();
}
System.out.println("Está conectado "+socket.isConnected()+"");
}
catch(IOException IOE)
{
throw new ExcecaoDeRede();
}
catch(ClassNotFoundException CNFE)
{
throw new ExcecaoDeRede();
}
}
public File recebeArquivo(String nomeDoArquivo)throws ExcecaoDeRede,ExcecaoDeClienteNaoConectado
{
if(this.estahConectado)
{
try
{
Mensagem<String> requisicao = new Mensagem(TipoDeMensagem.REQUISICAO_ENVIO_DE_ARQUIVO_DE_VIDEO,nomeDoArquivo);
saidaObjeto.writeObject( requisicao );
saidaObjeto.flush();
File arquivo = controlador.getArquivoDeVideoTemporario(nomeDoArquivo);
//System.out.println("Armazenando no arquivo "+arquivo.getPath()+"");
Mensagem<Integer> mensagem = (Mensagem<Integer>)entradaObjeto.readObject();
//System.out.println(mensagem);
if(mensagem.getTipoDeMensagem()==TipoDeMensagem.TRANSPORTE_INFORMACAO_DE_TAMANHO_DE_ARQUIVO)
{
DataOutputStream saidaArquivo = new DataOutputStream(new FileOutputStream(arquivo));
//O servidor envia o tamanho do arquivo que está para enviar, empacotado em um Integer
int bytesParaReceber = ((Integer)mensagem.getDados()).intValue();
int tamanhoDoFragmento = 1024;
byte[] dados = new byte[tamanhoDoFragmento];
int bytesLidos;
while(bytesParaReceber>0)
{
bytesLidos = (bytesParaReceber >= tamanhoDoFragmento ? tamanhoDoFragmento : bytesParaReceber);
System.out.println("Falta receber "+bytesParaReceber+" bytes");
entradaDado.read(dados,0,bytesLidos);
saidaArquivo.write(dados,0,bytesLidos);
bytesParaReceber = bytesParaReceber - bytesLidos;
try
{
Thread.sleep(0,1);
}
catch(InterruptedException IE)
{
continue;
}
}
saidaArquivo.close();
return arquivo;
}
else
{
System.out.println("Informação inesperada");
throw new ExcecaoDeRede();
}
}
catch(IOException IOE)
{
throw new ExcecaoDeRede();
}
catch(ClassNotFoundException CNFE)
{
throw new ExcecaoDeRede();
}
catch(Exception ex)
{
throw new ExcecaoDeRede();
}
}
else
{
//Excecao de cliente não conectado ao servidor
throw new ExcecaoDeClienteNaoConectado();
}
}
public void enviaDadosDoVideo(File arquivoDeVideo)throws Exception
{
if(this.estahConectado)
{
}
else
{
//Excecao e cliente não conectado ao servidor
throw new Exception();
}
}
public Vector<String> getListaDeVideosDoRepositorio()throws ExcecaoDeRede
{
try
{
saidaObjeto.writeObject( new Mensagem(TipoDeMensagem.REQUISICAO_ENVIO_DE_LISTA_DE_ARQUIVOS) );
saidaObjeto.flush();
Mensagem<Vector<String>> mensagem = (Mensagem<Vector<String>>)entradaObjeto.readObject();
if(mensagem.getTipoDeMensagem()==TipoDeMensagem.TRANSPORTE_LISTA_DE_VIDEOS)
{
return mensagem.getDados();
}
else
{
throw new ExcecaoDeRede();
}
}
catch(IOException IOE)
{
throw new ExcecaoDeRede();
}
catch(ClassNotFoundException CNFE)
{
throw new ExcecaoDeRede();
}
}
public void teste(String nomeDoArquivo)throws Exception
{
recebeArquivo(nomeDoArquivo);
}
public static void main(String[] s)
{
try
{
Cliente cliente = new Cliente("#$%Joel*Luis*Carbonera%$#", Controlador.getInstancia());
try
{
cliente.teste("teste.mpg");
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
Código do objeto Mensagem:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package comunicacao;
import java.io.Serializable;
/**
*
* @author usuario
*/
public class Mensagem <T> implements Serializable
{
private TipoDeMensagem tipoDeMensagem;//É um enum
private T dados;
public Mensagem(TipoDeMensagem tipoDeMensagem)
{
this.tipoDeMensagem = tipoDeMensagem;
this.dados = null;
}
public Mensagem(TipoDeMensagem tipoDeMensagem, T dados)
{
this.tipoDeMensagem = tipoDeMensagem;
this.dados = dados;
}
public TipoDeMensagem getTipoDeMensagem()
{
return tipoDeMensagem;
}
public T getDados()
{
return this.dados;
}
}
Código do enum TipoDeMensagem
public enum TipoDeMensagem implements Serializable
{
REQUISICAO_DE_CONFIRMACAO_DE_IDENTIDADE,
RESPOSTA_IDENTIDADE_CONFIRMADA,
RESPOSTA_IDENTIDADE_NAO_CONFIRMADA,
REQUISICAO_RECEBIMENTO_DE_ARQUIVO_DE_VIDEO,
REQUISICAO_ENVIO_DE_ARQUIVO_DE_VIDEO,
REQUISICAO_ENVIO_DE_LISTA_DE_ARQUIVOS,
TRANSPORTE_DE_DADOS_DE_VIDEO,
TRANSPORTE_LISTA_DE_VIDEOS,
TRANSPORTE_INFORMACAO_DE_TAMANHO_DE_ARQUIVO;
}