[Resolvido]Problema com Sockets, DatagramSocket, Multicast, DatagramPackets

Galera preciso de ajuda em uma aplicação minha que usa Sockets, DatagramSocket, Multicast, DatagramPackets. Eu tenho um servidor e um cliente, os dois são multi-threads. Antes de explicar já vou falar qual o problema. Rodando a aplicação com ip localhost( 127.0.0.1 ) ela funciona eu executando o servidor e abrindo mais de dois clientes. Agora executando o servidor em um servidor mesmo( tenho um servidor linux aqui em casa ) e abrindo o cliente na minha máquina usando o ip do servidor não funciona. Eu estou tentando depurar e acho que já sei onde é o problema só não sei como resolver. ( Lembrando que isso que vou falar agora se refere a quando rodo a aplicação servidor em um servidor mesmo ).

Eu fiz uns testes e vi que o cliente manda a mensagem para o servidor e o servidor recebe. Agora eu não sei se o servidor está mandando de volta porque o cliente parece ficar no loop de espera por pacotes e não recebe nada. Veja, o cliente manda mensagem para o servidor assim:

@Override
    public void run() {
        // Envia mensagem e descarrega PrintWriter
        try {
            Formatter output = new Formatter( clienteSocket.getOutputStream() );
            output.format( "%s\n", mensagemParaEnviar ); // envia mensagem
            output.flush();
        }
        catch( IOException ioE ) {
            ioE.printStackTrace();
        }
    }

O servidor recebe mensagem do cliente assim:

public class RecebedorDeMensagem implements Runnable {
    /** Fluxo de entrada para ler mensagens recebidas do cliente */
    private BufferedReader bufferInput;

    public RecebedorDeMensagem( MensagemListener listener, Socket clienteSocket ) {
        mensagemListener = listener;

        try {
            /** Configura tempo limite para leitura das mensages de um cliente - 5 segundos */
            clienteSocket.setSoTimeout( 5000 );

            bufferInput = new BufferedReader( new InputStreamReader( clienteSocket.getInputStream() ) );
        }
        catch( IOException e ) {
            e.printStackTrace();
        }
    } // fim do construtor

    /**
     * Escuta por novas mensagens e as entrega para MensagemListener
     */
    @Override
    public void run() {
        String mensagem;

        // Escuta por mensagens até parar
        while( continuaEscutando ) {
            try {
                /** String para mensagens recebidas. OBS: Se passar 5 segundos sem ler dados gera uma exceção */
                mensagem = bufferInput.readLine();
            }
            catch( SocketTimeoutException sTE ) {
                continue; // Continua para a próxima iteração do loop
            }
            catch( IOException ioE ) {
                ioE.printStackTrace();
                break;
            }
    } // fim do método run de Runnable

O servidor envia para os clientes de volta assim:

/**
     * Entrega mensagens para MULTICAST_ENDERECO sobre DatagramSocket
     */
    @Override
    public void run() {
        try {
            /** Cria DatagramSocket para enviar mensagens */
            DatagramSocket datagramSocket = new DatagramSocket( MULTICAST_PORTA_ENVIA );
            /** Usa um InetAdress reservado para um grupo multicast - O grupo de assinantes que desejam se conectar ao grupo */
            InetAddress grupo = InetAddress.getByName( MULTICAST_ENDERECO );
            /** Cria um DatagramPacket contendo a mensagem */
            DatagramPacket datagramPacket = new DatagramPacket( dadosDaMensagem, dadosDaMensagem.length, grupo, MULTICAST_PORTA_LISTENER );

            // Envia pacote para grupo Multicast - cada cliente recebe os pacotes
            datagramSocket.send( datagramPacket );
            datagramSocket.close();
        }
        catch( IOException ioE ) {
            ioE.printStackTrace();
        }
    } // fim do método run

e por último o cliente recebe mensagens do servidor assim:

public RecebedorDePacotes( MensagemListener listener ) {
        mensagemListener = listener;

        // Conecta MulticastSocket ao endereço Multicast e porta
        try {
            // Porta que o MulticastSocket irá escutar por novas mensagens
            multicastSocket = new MulticastSocket( MULTICAST_PORTA_LISTENER );
            // Usa InetAddress para receber grupo multicast
            multicastGrupo = InetAddress.getByName( MULTICAST_ENDERECO );
            // Se junta ao grupo multicast para receber mensagens enviadas do MULTICAST_ENDERECO
            multicastSocket.joinGroup( multicastGrupo );

            // Configura com 5 segundos como tempo limite para esperar novos pacotes - Previne RecebedorDePacotes do bloqueio indefinido
            // enquanto estiver esperando para receber novos DatagramPackets
            multicastSocket.setSoTimeout( 5000 );
        }
        catch( IOException ioE ) {
            ioE.printStackTrace();
        }
    } // fim do construtor

    @Override
    public void run() {
        // Escuta por novas mensagens até parar
        while( continuaEscutando ) {
            // Cria buffer para as mensagens recebidas
            byte[] buffer = new byte[ MENSAGEM_TAMANHO ];
            // Cria DatagramPacket para as mensagens recebidas
            DatagramPacket datagramPacket = new DatagramPacket( buffer, MENSAGEM_TAMANHO );

            // Recebe novos DatagramPackets( Bloqueando chamada )
            try {
                multicastSocket.receive( datagramPacket );
            }
            catch( SocketTimeoutException stE ) {
                continue; // continua para próxima iteração do loop
            }
            catch( IOException ioE ) {
                ioE.printStackTrace();
                break;
            }
            /** Coloca dados da mensagem na string */
            String mensagem = new String( datagramPacket.getData() );
        } // fim do loop while

Eu sei que nesse ultimo codigo que eu postei, essa linha fica bloqueada:

try {
                multicastSocket.receive( datagramPacket );
            }

Porque essa parte nunca chega( fazendo os meus testes percebi isso )

 /** Coloca dados da mensagem na string */
            String mensagem = new String( datagramPacket.getData() );
        } // fim do loop while

Porém ele fica rodando o run direto procurando por mensagens e parece nunca receber. O código aqui ta resumido foram apenas para quem quiser me ajudar entender como estou fazendo o envio e recebimento. O restou eu estou fazendo tambem mas não postei aqui tipo fechar a conexao, dizer quando parar de escutar e tal.

Já usou o wireshark para ver se o pacote está mesmo chegando a sua máquina?
Você tem na sua rede um endereço de multicast configurado? Muitos roteadores exigem que essa configuração seja feita explicitamente (do contrário do endereços de broadcast).

[quote=ViniGodoy]Já usou o wireshark para ver se o pacote está mesmo chegando a sua máquina?
Você tem na sua rede um endereço de multicast configurado? Muitos roteadores exigem que essa configuração seja feita explicitamente (do contrário do endereços de broadcast).
[/quote]

wireshark? o que é e para que serve? eu nao tenho como pesquisar agora pq eu to no cel. voce tem algum link sobre isso que voce falou? o roteador daqui de casa eu acho que e encore. o que eu configuro exatamente no roteador? o endereço multicast, a porta de enviar ou escutar? vlw pela ajuda. obrigado.

É uma aplicação que deixa vc ver o que está passando pela rede:
http://www.wireshark.org/

Basta filtrar pelo IP ou pela porta do seu servidor, e vc verá se os pacotes da sua aplicação estão chegando ou não.

[quote=ViniGodoy]É uma aplicação que deixa vc ver o que está passando pela rede:
http://www.wireshark.org/

Basta filtrar pelo IP ou pela porta do seu servidor, e vc verá se os pacotes da sua aplicação estão chegando ou não.[/quote]

Obrigado pela ajuda. Vou baixar e testar aqui. Qualquer dúvida posto aqui…

Filtrar pelo ip do multicast ou do servidor? Tenho que procurar como usar o programa porque não entendi nada dele.

Tanto faz.

Não achei nada sobre configuração de ip multicast no meu roteador… :cry: Será que eu não tenho que configurar o ip multicast no servidor linux?

Já viu no wireshark se o pacote está ou não chegando?

Filtrei pelo endereço ip do servidor e não achei pacote nenhum. Mais colocando uma mensagem de linha de comando na minha aplicação servidor. Quando eu digito a mensagem no cliente, o servidor le e exibe a mensagem( então está chegando)

Nesse caso, não deve ser problema do roteador.

Nesse caso, não deve ser problema do roteador.[/quote]

A mensagem está chegando no servidor mas não está chegando no cliente. Pelo wireshark não vi nenhum pacote udp envolvido com o meu ip ou o do servidor. O que faço agora?

Opa, opa, não filtrei por ip nenhum, botei para capturar tudo mesmo e no momento exato que eu digito uma mensagem no cliente e envio para o servidor aparece isso que está em vermelho na imagem

Vini se souber me ajude por favor nesse problema. Quando me conectei no servidor apareceu esse pacote( ele aparece de vez em quando só que diferente )

5 9.928941000 Cliente Servidor TCP 66 54181 > italk [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
6 9.930921000 Servidor Cliente TCP 66 italk > 54181 [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1460 SACK_PERM=1 WS=128
11 9.961439000 Cliente 239.0.0.1 IGMPv2 46 Membership Report group 239.0.0.1 [color=red]<-------------------ENDEREÇO MULTICAST[/color]

Consegui resolver o problema. O problema é que eu tava me conectando no sinal do roteador e no servidor e o servidor estava entre o wan do roteador e lan do modem. Ou seja ele estava no caminho. Quando eu me conectei direto no lan do modem no wan do roteador( por um cabo que tem aqui em casa ) ai funcionou. Não precisou ser feita configuração nenhuma.