Problema com socket - Servidor não consegue ler objeto

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; }

Aesceção ocorre na linha 85 do objeto Conexao:

Mensagem mensagem = (Mensagem)entradaObjeto.readObject();

Que está dentro do método run do objeto conexão.

A idéia é que ele fique esperando requisições do cliente ali dentro…No meu cenário de teste eu executo o main do Servidor e do Cliente. O cliente só se identifica e espera a identificação ser confirmada. O servidor identifica o cliente e entra no run. Ficaria esperando uma requisição do cliente, que nunca chegaria…

A exceção que dá é:
java.net.SocketException: Connection reset

Alguém sabe o que eu posso estar fazendo de errado?

Agradeço desde já…