Java não recebe pacotes

10 respostas
cesar.vog

Olá estou fazendo um aplicativo em Java que fica recebendo pacotes de um programa feito em c++
porém os pacotes não chegam, eu sei que o erro é no Java porque verifiquei e os pacotes estão saindo.

...
        BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
        DataInputStream recv = new DataInputStream(s.getInputStream()); //Cria a váriavel que irá receber os pacotes
        /*Loop principal*/
        while (true) {
            // cont = recv.readUTF();
            cont = in.readLine();
            System.out.println("pacote: " + cont);
        }
    } catch (IOException ex) {
        System.out.println("Algo aconteceu de errado ao receber o pacote");
    }

Como vocês podem ver tentei de duas vezes, com BufferedReader e sem mas nenhum deu certo.
a parte de conectar deu tudo certo, alguém pode me ajudar? :?

10 Respostas

ViniGodoy

Como é o seu protocolo?

ViniGodoy

Ah, bem-vindo ao GUJ. :slight_smile:

Outra coisa, ao postar códigos, por favor, use as seguintes dicas:
http://www.guj.com.br/posts/list/50115.java

cesar.vog

Estou usando sockets SDL no c++, mas oque estou mandando de lá é apenas uma string.
e obrigado pela dica.

BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
DataInputStream recv = new DataInputStream(s.getInputStream()); //Cria a váriavel que irá receber os pacotes
/*Loop principal*/
...
while (true) {
      // cont = recv.readUTF();
      cont = in.readLine();
      System.out.println("pacote: " + cont);
}
} catch (IOException ex) {
      System.out.println("Algo aconteceu de errado ao receber o pacote");
}
ViniGodoy

Ok, tudo bem. Você está usando os sockets através da SDL.

Se você só está mandando uma string, provavelmente o terminador dela é o \0, do C++. No Java, o terminador que o readline procura é o \n, ou o \r\n. Por isso, seu programa nunca irá retornar.

Para que uma aplicação socket funcione, você precisa definir um protocolo entre as duas pontas. Pode ser algo simples, como por exemplo, enviar um byte indicando o tamanho da mensagem e outro indicando o tipo de dado, antes de cada mensagem. Senão fica difícil saber como decodificar as coisas.

Dá uma lida nesse tópico, que vai te esclarecer melhor:
http://www.guj.com.br/posts/list/136538.java#735860

cesar.vog

Mal, agora que entendi sua pergunta, eu tenho sim um protocolo criado por mim
pra saber pegar valores e esse tipo de coisa, o problema é que como eu não recebia a string não tinha como “decodificar”

mas cara vlw era isso mesmo, coloquei para que no final do pacote fosse \n e funcinou
muito obrigado ^^

ViniGodoy

Como você está trabalhando com Java e C++, evite:

  1. Usar classes Reader, e métodos do tipo “ReadLine”. Use diretamente o DataInputStream ou, melhor ainda, a classe ByteBuffer do pacote java.nio;

  2. Colocar tipos “unsigned” no seu protocolo. Se fizer isso, terá que fazer promoções de tipos no lado do Java;

  3. Lembre-se do “endianess”. No C++, a ordenação dos bytes dependerá da plataforma utilizada. A classe ByteBuffer, do Java, já permite ajustar little e big endian. Na boost há métodos que fazem essa conversão também. Adote um padrão.

  4. Lembre-se que Strings java são Unicode, e o std::string é por padrão ascii 2. Dificilmente tive problemas com isso, mas vale lembrar que se você codificar um string diretamente num Reader, ele será codificado nesse padrão. Use, então, o getBytes() do lado do Java. Outra opção é usar a std::wstring() e trabalhar com unicode diretamente.

cesar.vog

obrigadão pelas dicas, vou me informar sobre essas classes.
esses mais difíceis de acontecer são também os mais difíceis de resolver heeh.

ViniGodoy

Eu sempre achei mais fácil e poderoso trabalhar com o boost::asio do que com os sockets da SDL.

A SDL é legal para tratamento de eventos, janelas, carga de imagens e integração com OpenGL… mas não vi nada realmente muito bom além disso (embora isso já seja muito). A parte de som é simples, mas se você quiser efeitos sonoros mais avançados é melhor usar a OpenAL.

Acho a parte de threads da boost melhor também. Mas claro, daria para optar em fazer tudo em SDL só para não ficar enchendo o projeto de libs, dependências e o escambau.

E

É só lembrar que se for usar o boost::asio, ou o SDL (ou qualquer outra coisa, por sinal) é melhor definir um protocolo como o ViniGodoy indicou, onde as mensagens são antecedidas por um header contendo o seu comprimento. O boost::asio tem um módulo de sockets assíncronos que é furiosamente veloz, mas se você usar mensagens com tamanho antecedido pelo comprimento. Se for tentar usar um protocolo do tipo “mensagens de texto” ele fica lento e é inviável você usar o modo assíncrono.

Protocolos texto são muito difíceis de trabalhar, como diga o próprio HTTP (que tem o header “Content-Length:” só para suprir essa deficiência).

ViniGodoy

Uma alternativa para se trabalhar em modo texto é mesclar as duas. Você faz um protocolo simples como:

4 bytes: tamanho de um xml
n bytes: o xml

Pode-se até usar um algoritmo de compactação simples para o xml também. A vantagem é que a maior parte das linguagens já implementa um parser de XML. E o formato é bastante resistente a mudanças e evoluções da aplicação.

Depois, basta definir o formato dos dados mesmo, que estarão dentro do xml. :wink:

Agora, um protocolo 100% binário é mais compacto. Considere utiliza-lo caso você tenha limitações de banda.

Criado 20 de outubro de 2009
Ultima resposta 20 de out. de 2009
Respostas 10
Participantes 3