Transferir matriz de inteiros por sockets? qual melhor stream? como usar?

6 respostas
T

Pessoal eu estou apanhando que nem menino aqui!

A minha aplicação tem que transferir uma matriz int [][] pro meu cliente e meu cliente devolver pra ele depois de alguns cálculos um mesmo tipo de objeto…

eu testei a parte de atender requisições, conexão já tá 100%! Só que o Stream de dados para transferir e como utilizar é que estou apanhando!

me ajudem please!

6 Respostas

T

Se eu estivesse no seu lugar, provavelmente eu iria definir um protocolo orientado a mensagens sobre o TCP/IP, e com mensagens em formato binário.

Para mandar um objeto qualquer, provavelmente eu iria serializá-lo dessa forma (não testei o código portanto deve haver algum “throws” ou “try/catch” que estou omitindo):

byte[] serializar (Serializable ser)
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream (baos);
    oos.writeObject (ser);
    oos.flush();
    oos.close();
    return baos.toByteArray();
}
Object desserializar (byte[] bytes)
{
    ByteArrayInputStream bais = new ByteArrayInputStream (bytes);
    ObjectInputStream ois = new ObjectInputStream (bais);
    Object ret = ois.readObject ();
    ois.close();
    return ret;
}

Não é bom encapsular um Socket em um ObjectInputStream/ObjectOutputStream porque dá muitos problemas. Acredite, já vi gente ser despedida por causa disso.

T

thingol:
Se eu estivesse no seu lugar, provavelmente eu iria definir um protocolo orientado a mensagens sobre o TCP/IP, e com mensagens em formato binário.

Para mandar um objeto qualquer, provavelmente eu iria serializá-lo dessa forma (não testei o código portanto deve haver algum “throws” ou “try/catch” que estou omitindo):

byte[] serializar (Serializable ser)
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream (baos);
    oos.writeObject (ser);
    oos.flush();
    oos.close();
    return baos.toByteArray();
}
Object desserializar (byte[] bytes)
{
    ByteArrayInputStream bais = new ByteArrayInputStream (bytes);
    ObjectInputStream ois = new ObjectInputStream (bais);
    Object ret = ois.readObject ();
    ois.close();
    return ret;
}

Não é bom encapsular um Socket em um ObjectInputStream/ObjectOutputStream porque dá muitos problemas. Acredite, já vi gente ser despedida por causa disso.

Entendi, só uma coisa que não enxerguei! Como meu int [][] matriz vira um byte[] ???

T

Um byte[][] é um objeto, então pode ser serializado.

T

Peguei a ideía só que olha o problema:

Código do meu cliente:

System.out.println("Fazendo conexão ao servidor");
            meuCliente = new Socket("localhost", 1024);
            System.out.println("Conexão estabelecida");
            baos = new ByteArrayOutputStream();
            output = new ObjectOutputStream(baos);
            output.writeObject(matrizA);
            output.flush();
            baos.writeTo(meuCliente.getOutputStream());
            baos.flush();

Código da thread do servidor para atender as requisições:

input = (cliente.getInputStream());
            input.read(b); // AQUI DEBUGANDO O PROGRAMA GERA UMA EXCESSÃO E SAI
            bais = new ByteArrayInputStream(b);
            ois = new ObjectInputStream(bais);

o que pode ser ein? Pq ele tá dando pau na hora de ler meu input?

T

Thingol,

Consegui usar aqui tanto serializando via array de bytes como utilizando ObjectOutputStream.

Porquê você fez esse comentário acima? Qual o problema de se utilizar ObjectInputStream? Vi até mesmo documentos e em forums da SUN recomendando serialização dessa maneira quando se trata de comunicação entre duas aplicações JAVA.

Ai fiquei meio receoso e gostaria de saber os contras de se utilizar com SOCKET a classe ObjectOutputStream.

[]'s

T

O problema basicamente é o seguinte: quando você envia algo via ObjectOutputStream, o objeto ObjectOutputStream cria uma estrutura de dados interna contendo TODOS os objetos que já foram enviados.

Isso é porque você pode por exemplo enviar algum objeto que tenha referências a objetos que já foram enviados - então ele não precisa enviar isso de novo, não?

E do outro lado, o ObjectInputStream lê os dados recebidos, e também tem uma estrutura de dados interna contendo TODOS os objetos que já foram recebidos. Isso é para poder remontar o objeto, exatamente da forma que você estava esperando.

O problema é que isso pode acabar fritando os dois lados, porque você normalmente não faz referências a objetos já enviados em seus objetos. O que ocorre é que os dois lados acabam esgotando a memória do Java porque os objetos nunca são removidos.

Para quebrar esse galho, existe um método em ObjectOutputStream chamado “reset” (se não me engano). Ele faz o seguinte:

  1. Limpa essa estrutura de dados que contém os objetos já enviados;
  2. Envia um comando especial ao ObjectInputStream para limpar a estrutura de dados que contém os objetos já recebidos.

Só que antes de ele descobrir isso, já era tarde, e a solução foi simplesmente abortada.

Criado 17 de setembro de 2008
Ultima resposta 18 de set. de 2008
Respostas 6
Participantes 2