Dúvida com socket's

16 respostas
Yago_Ernandes

É o seguinte, eu tenho que desenvolver um programa de ponto eletrônico pra minha empresa, meu chefe falou pra eu estudar Sockets (que eu nem sabia o que era) ai eu comecei a estudar e decidi fazer um chat só pra fins educativos...

O problema é que o chat que eu fiz não estava mandando mensagens um para o outro, ai eu peguei alguns scripts na net pra ver como era e eles também não estão mandando mensagens...

O código é o seguinte:

- Cliente

package socketChat;

// ClienteDeChat.java
import java.io.*;
import java.net.*;
public class cliente extends Thread {

   // Flag que indica quando se deve terminar a execução.
   private static boolean done = false;

   // parte que controla a recepção de mensagens deste cliente
   private Socket conexao;

   // construtor que recebe o socket deste cliente
   public cliente(Socket s) {

      conexao = s;

   }

   // execução da thread
   public void run() {

      try {

         BufferedReader entrada = new BufferedReader(new InputStreamReader(conexao.getInputStream()));

         String linha;

            while (true) {

               // pega o que o servidor enviou
               linha = entrada.readLine();

               // verifica se é uma linha válida. Pode ser que a conexão
               // foi interrompida. Neste caso, a linha é null. Se isso
               // ocorrer, termina-se a execução saindo com break
               if (linha == null) {

                  System.out.println("Conexão encerrada!");

                  break;

               }

            // caso a linha não seja nula, deve-se imprimi-la
            System.out.println();

            System.out.println(linha);

            System.out.print("...> ");

         }

      } catch (IOException e) {

         // caso ocorra alguma exceção de E/S, mostre qual foi.
         System.out.println("IOException: " + e);

      }

   // sinaliza para o main que a conexão encerrou.
   }

   public static void main(String args[]) {
       String linha;
      try {

         // Para se conectar a algum servidor, basta se criar um objeto da classe Socket. O primeiro parâmetro é o IP ou
         // o endereço da máquina a qual se quer conectar e o segundo parâmetro é a porta da aplicação. Neste caso,
         // utiliza-se o IP da máquina local (127.0.0.1) e a porta da aplicação ServidorDeChat. Nada impede a mudança
         // desses valores, tentando estabelecer uma conexão com outras portas em outras máquinas.
         
          Socket conexao = new Socket("127.0.0.1", 2222);

         // uma vez estabelecida a comunicação, deve-se obter os
         // objetos que permitem controlar o fluxo de comunicação
         PrintStream saida = new PrintStream(conexao.getOutputStream());

         // enviar antes de tudo o nome do usuário
         BufferedReader teclado = new BufferedReader(new InputStreamReader(System.in));

         System.out.print("Entre com o seu nome: ");

         String meuNome = teclado.readLine();

         saida.println(meuNome);

         // Uma vez que tudo está pronto, antes de iniciar o loop
         // principal, executar a thread de recepção de mensagens.
         Thread t = new cliente(conexao);

         t.start();

         // loop principal: obtendo uma linha digitada no teclado e
         // enviando-a para o servidor.
         while (true) {

            // ler a linha digitada no teclado
            System.out.print("> ");

            linha = teclado.readLine();

            // antes de enviar, verifica se a conexão não foi fechada
            if (done) {break;}

            // envia para o servidor
            saida.println(linha);


         }

      } catch (IOException e) {

         // Caso ocorra alguma excessão de E/S, mostre qual foi.
         System.out.println("IOException: " + e);

      }

   }

}

- Servidor

package socketChat;

// ServidorDeChat.java

import java.io.*;
import java.net.*;
import java.util.*;

public class servidor extends Thread {

   // Parte que controla as conexões por meio de  threads.
   // Note que a instanciação está no main.
   private static Vector clientes;

   // socket deste cliente
   private Socket conexao;

   // nome deste cliente
   private String meuNome;

   // construtor que recebe o socket deste cliente
   public servidor(Socket s) {

      conexao = s;

   }

   // execução da thread
   public void run() {

      try {

         // objetos que permitem controlar fluxo de comunicação
         BufferedReader entrada = new BufferedReader(new InputStreamReader(conexao.getInputStream()));

         PrintStream saida = new PrintStream(conexao.getOutputStream());

         // primeiramente, espera-se pelo nome do cliente
         meuNome = entrada.readLine();

         // agora, verifica se string recebida é valida, pois
         // sem a conexão foi interrompida, a string é null.
         // Se isso ocorrer, deve-se terminar a execução.
         if (meuNome == null) {return;}

         // Uma vez que se tem um cliente conectado e conhecido,
         // coloca-se fluxo de saída para esse cliente no vetor de
         // clientes conectados.
         clientes.add(saida);

         // clientes é objeto compartilhado por várias threads!
         // De acordo com o manual da API, os métodos são
         // sincronizados. Portanto, não há problemas de acessos
         // simultâneos.

         // Loop principal: esperando por alguma string do cliente.
         // Quando recebe, envia a todos os conectados até que o
         // cliente envie linha em branco.
         // Verificar se linha é null (conexão interrompida)
         // Se não for nula, pode-se compará-la com métodos string
         String linha = entrada.readLine();

         while (linha != null && !(linha.trim().equals(""))) {

            // reenvia a linha para todos os clientes conectados
            sendToAll(saida, " disse: ", linha);

            // espera por uma nova linha.
            linha = entrada.readLine();

         }

         // Uma vez que o cliente enviou linha em branco, retira-se
         // fluxo de saída do vetor de clientes e fecha-se conexão.
         sendToAll(saida, " saiu ", "do chat!");

         clientes.remove(saida);

         conexao.close();

      } catch (IOException e) {

         // Caso ocorra alguma excessão de E/S, mostre qual foi.
         System.out.println("IOException: " + e);

      }

   }

   // enviar uma mensagem para todos, menos para o próprio
   public void sendToAll(PrintStream saida, String acao, String linha) throws IOException {

      Enumeration e = clientes.elements();

      while (e.hasMoreElements()) {

         // obtém o fluxo de saída de um dos clientes
         PrintStream chat = (PrintStream) e.nextElement();

         // envia para todos, menos para o próprio usuário
         if (chat != saida) {chat.println(meuNome + acao + linha);}

      }

   }

   public static void main(String args[]) {

      // instancia o vetor de clientes conectados
      clientes = new Vector();

      try {

         // criando um socket que fica escutando a porta 2222.
         ServerSocket s = new ServerSocket(2222);

         // Loop principal.
         while (true) {

            // aguarda algum cliente se conectar. A execução do
            // servidor fica bloqueada na chamada do método accept da
            // classe ServerSocket. Quando algum cliente se conectar
            // ao servidor, o método desbloqueia e retorna com um
            // objeto da classe Socket, que é porta da comunicação.
            System.out.print("Esperando alguem se conectar...");

            Socket conexao = s.accept();

            System.out.println("Conectou!");

            // cria uma nova thread para tratar essa conexão
            Thread t = new servidor(conexao);

            t.start();

            // voltando ao loop, esperando mais alguém se conectar.
         }

      } catch (IOException e) {

        // caso ocorra alguma excessão de E/S, mostre qual foi.
        System.out.println("IOException: " + e);

      }

   }

}

16 Respostas

Yago_Ernandes

É meio grandinho mas é bem simples… Eu já entendi como fazer, mas não entendi porque não ta trocando mensagens

david.cs20

Da algum erro ?!

T

bom dia,

ta falando que conectou, linha 129?

a primeira coisa q eu tentaria é verificar o firewall, talves ele esta bloqueando a porta ou a sua aplicacao…

Yago_Ernandes

não da erro nenhum =/

Yago_Ernandes

Vou fazer uma descrição do que acontece aqui… (em todos os scripts que eu tentei e nos que eu fiz acontece a mesma coisa)

1 - Eu inicio o servidor, e ele fica aguardando conexão;

2 - Quando eu conecto com o cliente, o servidor mostra que a conexão foi feita

3 - Quando envio uma mensagem do servidor pro cliente ele não recebe (e vice-versa)

Em nenhuma parte o programa da erro… Eu já dei umas vasculhadas no meu firewall e coloquei exceções para o processo do java e do netbeans

T

so um chute, ao inves de pegar oq o usuario digita, tenta enviar uma variavel com uma string do tipo “teste1”, se conecta acho q nao é o firewall

caio.ribeiro.pereira

Yago Ernandes, o seu código servidor.java esta meio estranho em uma coisa, me corrija se estiver errado, ok?

Você esta definiu na classe servidor o atributo clientes como privado estatico, e você esta instanciando ela no inicio da main e não no construtor da classe Servidor, alias nem precisa ser estatico esse atributo, visto que na boa pratica você teria que instância-la no construtor da classe Servidor.

Com isso talvez seu servidor não esta recebendo os clientes corretamente.

simplesmente faça isso:

private Socket conexao;
private Vector clientes;

public servidor(Socket s){
     conexao = s;
     clientes = new Vector();

}

espero que resolva com isso :smiley:

Yago_Ernandes

como assim?

Yago_Ernandes

Ah sim, entendi o que tu quis dizer… Tentei fazer essa modificações que você mostrou e continua sem funcionar.

Quando fui testar percebi uma coisa, ele conecta com o cliente e continua a receber conexões, será que isso tem algo a ver?

falo isso pois em todos os outros programas dava o mesmo erro mas não tinha threds pra receber novas conexões

caio.ribeiro.pereira

Cara já que você apenas ta estudando e fazendo testes com um mini-chat, da uma olhada nessa apostila de Java da Caelum, lá tem um capítulo que eles fazem um mini-chat muito parecido com o seu, testa o código deles, se mesmo assim continuar erro, então deve ser problema de firewall que você ainda não checou direito.

Java FJ11

Yago_Ernandes

Vou dar uma lida, valeu pela dica

pmlm

O teu código funciona!

Tu não estás a mandar mensagens entre cliente e servidor mas sim de um cliente para todos os outros. Só com um cliente não consegues testar. Experimenta com dois.

Yago_Ernandes

exatamente… Mesmo de cliente para cliente não consigo enviar as mensagens, tem alguma coisa errada só com meu pc. Os scripts que eu peguei na internet(que nos comentários as pessoas falavam que dava certo) no meu computador não funcionou.

Alguém sabe o que pode estar acontecendo?

obs: Não é o firewall, eu já coloquei exceção para os processos, já tentei com ele desligado mas nada parece adiantar.

pmlm

Eu testei aqui e funcionou sem problema.

A

O servidor não está configurado para exibir as msgs recebidas

tenta alterar essa parte do codigo do server

while (linha != null && !(linha.trim().equals(""))) {  
  
            // reenvia a linha para todos os clientes conectados  
            sendToAll(saida, " disse: ", linha);  

           //Insira essa linha para exibir o texto que chega dos clientes (  exibe a msg, sem mostrar qm enviou etc.. )
           System.out.println(linha);
  
            // espera por uma nova linha.  
            linha = entrada.readLine();  
  
}

Seu servidor está configurado para receber a mensagem e fazer o broadcast.
[color=red] Nesse código, o Servidor não envia mensagem para os clientes[/color]

Outra forma de testar esse código é abrir 2 clientes

Yago_Ernandes

Ai gente, agora ta funcionando beleza, como eu ja suspeitava, o problema tava no meu sistema operacional bugado (Windows 7 Home Premium é um lixo), eu formatei o computador e coloquei o Ultimate, agora todos os códigos estão funcionando sem problemas…

O código disponibilizado no FJ11 prestou até no sistema anterior! Muito bom ele…

Muito obrigado pela atenção. Até mais…

Criado 8 de junho de 2012
Ultima resposta 13 de jun. de 2012
Respostas 16
Participantes 6