Socket - DataOutputStream inconsistente

0 respostas
dwduncan

Boa tarde senhores, após pesquisar no google e ler algumas referências aqui do guj, pude ver que não é recomendável utilizar ObjectOutputStream em conexões via socket.
Tudo bem, implementei utilizando DataOutputStream, e aí do outro lado leio com DataInputStream. O problema é que na leitura pude ver que a sequencia por vezes e aleatoriamente chega com menos bytes do que deveria.

try{

            if (Atualizador.getServidor() == null) throw new ServidorLocalException();

            DataInputStream input = null;
            DataOutputStream output = null;

            long idServer = Atualizador.getServidor() == null || Atualizador.getServidor().getServidor() == null ? 0
                    : Atualizador.getServidor().getServidor().getIdConferencia();

            String ip = Servidor.IP_SERVIDOR_MASTER;
            while(!Thread.currentThread().isInterrupted() || encerrar){
                try{
                    setStatus("RODANDO");
                    socket = new Socket(ip, getPorta());

                    Map<Atualizavel,List> mapaEnvio = this.getMapaEnvio(1);
                    byte[] dadosEnvio = Atualizador.getConversor().getBytesObjeto(mapaEnvio);
                    String md5Envio = Criptografa.criptografaMD5(dadosEnvio);
                    int tamanhoEnvio = dadosEnvio.length;

                    System.out.println("Servidor Secundário: Tentando conexão.. " + ip + ":" + getPorta());

                    input = new DataInputStream(socket.getInputStream());
                    output = new DataOutputStream(socket.getOutputStream());

                    output.writeLong(idServer);
                    output.writeInt(tamanhoEnvio);
                    output.writeUTF(md5Envio);

                    System.out.println("Servidor Secundário: Total enviado... " + tamanhoEnvio + " ID:" + idServer);

                    int idx = 0, quantEnviada = 0;
                    while(quantEnviada < tamanhoEnvio){
                        int tam = Atualizador.TAMANHO_ARRAY;
                        if (tamanhoEnvio - quantEnviada < Atualizador.TAMANHO_ARRAY){
                            tam = tamanhoEnvio - quantEnviada;
                        }
                        output.write(dadosEnvio, idx, tam);
                        quantEnviada += tam;
                        idx += tam;
                    }

                    output.flush();
                    System.out.println("Servidor Secundário: Mapa enviado...");
                    boolean envioSucesso = input.readBoolean();
                    int tamanhoRecebido = input.readInt();
                    String md5Recebida = input.readUTF();

                    byte[] recebidos = new byte[tamanhoRecebido];

                    idx = 0;
                    int quantRecebida = 0;
                    while(tamanhoRecebido > quantRecebida){
                        int tam = Atualizador.TAMANHO_ARRAY;
                        if (tamanhoRecebido - quantRecebida < Atualizador.TAMANHO_ARRAY){
                            tam = tamanhoRecebido - quantRecebida;
                        }
                        System.out.println("LENDO ---------->" + input.read(recebidos, idx, tam));
                        quantRecebida += tam;
                        idx += tam;
                    }
                    

                    Map<Atualizavel,List> mapaRecebido = null;
                    boolean recepcaoBemSucedido = false;
                    
                    //Confere a md5 enviada com a recebida, se ok carrega os dados no bd.
                    String md5RecebidaAConferir = Criptografa.criptografaMD5(recebidos);
                    System.out.println("Servidor Secundário: md5RecebidaAConferir=" + md5RecebidaAConferir
                            + "        md5Recebida=" + md5Recebida);
                    if (md5RecebidaAConferir != null && md5Recebida != null){
                        mapaRecebido = Atualizador.getConversor().getObjeto(recebidos);
                        recepcaoBemSucedido = md5RecebidaAConferir.equalsIgnoreCase(md5Recebida);
                    }

                    
                    output.writeBoolean(recepcaoBemSucedido);

                    output.flush();

                    input.close();
                    output.close();
                                        

                    if (recepcaoBemSucedido){                        
                        super.carregarDados(mapaRecebido, 1);
                        System.out.println("Servidor Secundário: Dados carregados... ");
                    }

                    if (envioSucesso){
                        System.out.println("Servidor Secundário: Dados marcados... ");
                        super.marcarEnviados(mapaEnvio, 1);
                    }

                    System.out.println("\n\n");

                }catch(ConnectException ce){

                }catch(SocketException se){

                }catch(NullPointerException npe){

                }

O código do outro lado:

try{
            input = new DataInputStream(getSocket().getInputStream());
            output = new DataOutputStream(getSocket().getOutputStream());
            //Recebe o codigo de replicacao do servidor secundário
            this.setCodigoAtualizacao(input.readLong());
            //Recebe o tamanho do array[] que será enviado
            this.setTamanhoRecebido(input.readInt());
            //Recebe para futura conferencia um md5 correspondente ao array de bytes
            this.setMd5Recebida(input.readUTF());
            byte[] recebidos = new byte[this.getTamanhoRecebido()];

            System.out.println("Servidor Master Recebendo... id: " + this.getCodigoAtualizacao() + " Total Bytes: " + this.getTamanhoRecebido());

            //recebe os pacotes do array[]
            int idx = 0;
            while(this.getQuantidadeRecebida() < this.getTamanhoRecebido()){
                int tam = Atualizador.TAMANHO_ARRAY;
                if (this.getTamanhoRecebido() - this.getQuantidadeRecebida() < Atualizador.TAMANHO_ARRAY){
                    tam = this.getTamanhoRecebido() - this.getQuantidadeRecebida();
                }
                input.read(recebidos, idx, tam);
                this.adicionaQuantidadeRecebida(tam);
                idx += tam;
            }
            System.out.println("Servidor Master Recebendo... Mapa do servidor secundário...");
            //Confere a md5 enviada com a recebida, se ok carrega os dados no bd.
            String md5RecebidaAConferir = Criptografa.criptografaMD5(recebidos);
            if (md5RecebidaAConferir != null && this.getMd5Recebida() != null){
                this.setRecepcaoBemSucedido(md5RecebidaAConferir.equalsIgnoreCase(this.getMd5Recebida()));
                this.setMapaRecebido(conversor.getObjeto(recebidos));
            }

            System.out.println("Servidor Secundário: md5RecebidaAConferir=" + md5RecebidaAConferir
                            + "        md5Recebida=" + md5Recebida);

            //Prepara o mapa de dados que deverão ser enviados para o servidor secundário
            Map<Atualizavel,List> mapaEnvio = AtualizadorMaster.getInstance().getMapaEnvio(this.getCodigoAtualizacao());

            System.out.println("Servidor Master Mapa preparado para envio ");
            //Converte o mapa em array[]
            byte[] dadosEnvio = conversor.getBytesObjeto(mapaEnvio);
            String md5Envio = Criptografa.criptografaMD5(dadosEnvio);

            
            int tamanho = dadosEnvio.length;
            int quantEnviada = 0;
            output.writeBoolean(this.isRecepcaoBemSucedido());
            output.writeInt(tamanho);
            output.writeUTF(md5Envio);

            System.out.println("Servidor Master Total a enviar----> tamanho: " + tamanho + "   MD5 Envio: " + md5Envio );
            idx = 0;
            while(quantEnviada < tamanho){
                int tam = Atualizador.TAMANHO_ARRAY;
                if (tamanho - quantEnviada < Atualizador.TAMANHO_ARRAY){
                    tam = tamanho - quantEnviada;
                }
                output.write(dadosEnvio, idx, tam);
                System.out.println("Escrito --------> " + idx + "  len: " + tam);
                quantEnviada += tam;
                idx += tam;
                output.flush();
            }

            

            this.setEnvioBemSucedido(input.readBoolean());


            if (this.isEnvioBemSucedido()){
                AtualizadorMaster.getInstance().marcarEnviados(mapaEnvio, codigoAtualizacao);
                System.out.println("Servidor Master marcando dados... ");
            }


            if (this.isRecepcaoBemSucedido()){
                AtualizadorMaster.getInstance().carregarDados(mapaRecebido, codigoAtualizacao);
                System.out.println("Servidor Master carregando dados... ");
            }

            System.out.println("\n\n");

        }catch(Exception ex){
            ex.printStackTrace();
        }finally{
            try{
                input.close();
                output.close();
                socket.close();
            }catch(Exception ex){}
        }
    }

Em seguida fiz uma leitura dos dados, e na recepção ocorre o seguinte:
Servidor Secundário: Mapa enviado…
LENDO ---------->512
LENDO ---------->512
LENDO ---------->512
LENDO ---------->512
LENDO ---------->512
LENDO ---------->321
LENDO ---------->512
LENDO ---------->94
Servidor Secundário: md5RecebidaAConferir=e37e5da97cc0e8904a72a0c50bdd723a md5Recebida=fdf9e870bd995f3126dea875272ede2c

Só para resumir, no 6º "LENDO" deveriar estar 512 (Confirmado 512 no envio) (nesse array recebido houve, acredito, ulguma perda de dados) isso ocorre de forma aleatória e ora vem 512 ora não.

Alguém saberia dizer como fazer algo mais estável ?

ps. a rede está ok cabeamento novo, ativos novos e testados com diferentes equipamentos, a culpa não é da rede.

Desde já obrigado.

Criado 21 de outubro de 2009
Respostas 0
Participantes 1