Problema ao enviar mensagem via socket

Olá pessoal,

tenho na classe servidor uma thread que fica aguardando uma conexão, após abre os streams e recebe uma mensagem.

Servidor

[code]public class ServidorThread extends Thread {

private ServidorConexao servidorConexao;

public ServidorThread(ServidorConexao servidorConexao) {
this.servidorConexao = servidorConexao;
}

@Override
public void run(){
try{
do {
this.servidorConexao.aguardaConexao();
this.servidorConexao.abreStreams();
System.out.println(“passou abre streams”);
//ao receber uma mensagem
this.servidorConexao.receberMensagem();

        ServidorThread.sleep(2000);
      
     } while(this.servidorConexao.isServidorIniciado());

     } catch(Exception ex) {
   System.out.println("ServidorThread - Ocorreu um Erro: " + ex.toString());
  }

}

}[/code]

E a classe servidorconexao com o principal somente:

public class ServidorConexao {

   private ServerSocket welcomeSocket;
   private Socket connectionSocket;
   private ServidorGUI servidorGUI;
   private ServidorThread servidorThread;

   private DataInputStream sInput;
   private DataOutputStream sOutput;

   ...

public void iniciarServidor() {
      try {
      this.welcomeSocket = new ServerSocket(22285);
      System.out.println("Servidor Iniciado na Porta 22285;");

         this.servidorThread = new ServidorThread(this); 
         this.servidorThread.start();
         this.setServidorIniciado(true);

        } catch (IOException ex) {
            System.out.println("0)Ocorreu um Erro: " + ex.toString());
        }
   }

   public synchronized void aguardaConexao() {
      try {         
         this.connectionSocket = this.welcomeSocket.accept(); //ao receber
      } catch (IOException ex) {
         Logger.getLogger(ServidorConexao.class.getName()).log(Level.SEVERE, null, ex);
      }
   }

 public void abreStreams() {
      try {
         this.sOutput = new DataOutputStream(connectionSocket.getOutputStream());
         this.sInput = new DataInputStream(connectionSocket.getInputStream());
         System.out.println("passou abre streams");
      } catch (IOException ex) {
         Logger.getLogger(ServidorConexao.class.getName()).log(Level.SEVERE, null, ex);
      }
   }

///////// PONTO 1 - O PROBLEMA está acontecendo na linha "while ((((caractere = sInput.read()) != -1))) " 
/////// Ele trava nesta linha dentro do comando read (SocketInputStream...), e não acontece mais nada, se eu não faço o output.close() no cliente.
 
public synchronized void receberMensagem() throws IOException, ClassNotFoundException {
      int caractere;
      StringBuilder buffer = new StringBuilder();
	// Leitura dos caracteres enviados pelo cliente

         while ((((caractere = sInput.read()) != -1))) {   // <<<< aqui
            // Armazenamento dos caracteres
            buffer.append((char)caractere);
         }

         String[] dados = buffer.toString().trim().split(";");

         // Ação = 1 = efetua busca
         if (dados[0].equals("1)) {
         //recebeu a mensagem do cliente que vai enviar a lista dos arquivos do cliente
            this.recebeLista();
         }
   }

O que acontece é que, o cliente envia normalmente a mensagem, e o servidor recebe, mas tem um porém.
Na classe cliente, aonde eu envio a mensagem, está assim:
(eu chamdo o StartSocket direto da interface com o usuario)

Cliente

public  class Cliente {
    private SocketConnection client;
    private DataInputStream  input;
    private DataOutputStream  output;

    private String ipServidor;
      
    public synchronized void StartSocket(final String ip){
        new Thread(){
            public void run(){
                try {
                    client = (SocketConnection) Connector.open("socket://"+ip+":22285",Connector.READ_WRITE);
                    output = client.openDataOutputStream();
                    input = client.openDataInputStream();
                    client.setSocketOption(client.KEEPALIVE, 1);

                } catch (Exception ex) {
                    System.out.println("erro na conexão ao servidor: "+ex.toString() + " + "+ ex.getMessage());
                }
            }
        }.start();
    }

   ////// PONTO 2 - Se eu deixo linha do this.output.close; habilitada ele faz o envio e recebimento correto da mensagem, mas fecha o output, que eu não quero, porque depois eu quero enviar um arquivo pelo mesmo output
////// se eu deixo  a linha do this.output.close ; comentada, ele trava no "PONTO 1" como comentei ali em cima e fica travado.

public synchronized void enviarMensagem(String mensagem) throws IOException {
      
     this.output.write(mensagem.getBytes(),0, mensagem.length());

     this.output.flush();
     this.output.close();        // <<<<< AQUI
     //this.mensagem = null;
    }

Comentei no código, o PONTO 1 e PONTO 2.

No método aonde eu vou enviar o arquivo, APÓS esta mensagem está assim:

 public synchronized  void enviaLista(String arquivoCliente) {
      try {
            this.output = new DataOutputStream(client.openDataOutputStream());

         //this.output = client.openDataOutputStream();

         FileConnection fcup = (FileConnection)Connector.open(arquivoCliente, Connector.READ);

         input = fcup.openDataInputStream();
        
         byte[] buffer = new byte[512];
         int readed = -1;
         while ((readed = input.read(buffer))!= -1){
            output.write(buffer); //,0,readed);
         }
         output.flush();
         ///////client.close();
      } catch (IOException ex) {
         //System.out.println("Erro no envio da lista ao servidor: "+ex.toString() + " + "+ ex.getMessage());
         ex.printStackTrace();
      }
   }

Nas duas primeiras linhas do metodo enviaLista, eu tento “abrir” um novo DataOutputStream, mas qualquer uma das duas linhas, levanta a exceção:
java.io.IOException: no more output streams available

Alguém tem alguma ideia? Já revirei por tudo e não dá jeito. :cry:

No ponto 1, o problema é que você usou um método “blocking”, ele trava mesmo, só retorna quando consegue ler dados do socket. O outro problema é após o ponto 2, você não precisa dar um open de novo no seu client para pegar o output, ele já está definido.

No ponto 1, o método blocking que você comenta, seria o sInput.read() ?

O problema, é que ele não trava somente quando eu dou um close no cliente, la no Ponto 2.
Aí, se eu dou um close no output, em seguida, eu preciso mandar um arquivo pelo output, quer dizer que o unico jeito de fazer isso é fazer outra conexão atrabés do Connector.open e tudo mais?
Eu nao tenho como reutilizar o socket já criado?

PS: outra coisa, no Ponto 1, o input.read() ele começa a ler normalmente, mas se o output não foi fechado (close) no cliente, ele trava antes de terminar de ler.

Eu realmente estou precisando de ajuda nisto… :cry: :cry: :cry: :cry: :cry:

tem como eu enviar um arquivo por um outputstream (socket), receber no cliente pelo inputstream, sem ser obrigado a fechar (output.close) o outputstream?

Sim, problema é no sInput.read(), utilize outro read() do objeto para ler os dados. Quando voce dá um close no cliente ele volta mesmo, pois é o fim do fluxo. Quando você enviar o arquivo, no final apenas dê um flush para o cliente pegar.

O stream pode ficar aberto indefinidamente, você não precisa ficar abrindo e fechando para enviar vários arquivos, o que você precisa é de uma conexão de controle, onde você sinaliza o que está enviando numa conexão e faz a leitura dos dados na outra.

Mas o que acontece, é que se eu nao faço o output.close ele sempre trava… mesmo dando o flush, se nao fizer o close, ele trava no read()…

voce conseguiu resolver??? me envia os arquivos do codigo completo para eu dar uma olhada…

me manda os arquivos do cliente e do server para eu analisar…

[quote=saddam]Olá pessoal,

tenho na classe servidor uma thread que fica aguardando uma conexão, após abre os streams e recebe uma mensagem.

Servidor

[code]public class ServidorThread extends Thread {

private ServidorConexao servidorConexao;

public ServidorThread(ServidorConexao servidorConexao) {
this.servidorConexao = servidorConexao;
}

@Override
public void run(){
try{
do {
this.servidorConexao.aguardaConexao();
this.servidorConexao.abreStreams();
System.out.println(“passou abre streams”);
//ao receber uma mensagem
this.servidorConexao.receberMensagem();

        ServidorThread.sleep(2000);
      
     } while(this.servidorConexao.isServidorIniciado());

     } catch(Exception ex) {
   System.out.println("ServidorThread - Ocorreu um Erro: " + ex.toString());
  }

}

}[/code]

E a classe servidorconexao com o principal somente:

public class ServidorConexao {

   private ServerSocket welcomeSocket;
   private Socket connectionSocket;
   private ServidorGUI servidorGUI;
   private ServidorThread servidorThread;

   private DataInputStream sInput;
   private DataOutputStream sOutput;

   ...

public void iniciarServidor() {
      try {
      this.welcomeSocket = new ServerSocket(22285);
      System.out.println("Servidor Iniciado na Porta 22285;");

         this.servidorThread = new ServidorThread(this); 
         this.servidorThread.start();
         this.setServidorIniciado(true);

        } catch (IOException ex) {
            System.out.println("0)Ocorreu um Erro: " + ex.toString());
        }
   }

   public synchronized void aguardaConexao() {
      try {         
         this.connectionSocket = this.welcomeSocket.accept(); //ao receber
      } catch (IOException ex) {
         Logger.getLogger(ServidorConexao.class.getName()).log(Level.SEVERE, null, ex);
      }
   }

 public void abreStreams() {
      try {
         this.sOutput = new DataOutputStream(connectionSocket.getOutputStream());
         this.sInput = new DataInputStream(connectionSocket.getInputStream());
         System.out.println("passou abre streams");
      } catch (IOException ex) {
         Logger.getLogger(ServidorConexao.class.getName()).log(Level.SEVERE, null, ex);
      }
   }

///////// PONTO 1 - O PROBLEMA está acontecendo na linha "while ((((caractere = sInput.read()) != -1))) " 
/////// Ele trava nesta linha dentro do comando read (SocketInputStream...), e não acontece mais nada, se eu não faço o output.close() no cliente.
 
public synchronized void receberMensagem() throws IOException, ClassNotFoundException {
      int caractere;
      StringBuilder buffer = new StringBuilder();
	// Leitura dos caracteres enviados pelo cliente

         while ((((caractere = sInput.read()) != -1))) {   // <<<< aqui
            // Armazenamento dos caracteres
            buffer.append((char)caractere);
         }

         String[] dados = buffer.toString().trim().split(";");

         // Ação = 1 = efetua busca
         if (dados[0].equals("1)) {
         //recebeu a mensagem do cliente que vai enviar a lista dos arquivos do cliente
            this.recebeLista();
         }
   }

O que acontece é que, o cliente envia normalmente a mensagem, e o servidor recebe, mas tem um porém.
Na classe cliente, aonde eu envio a mensagem, está assim:
(eu chamdo o StartSocket direto da interface com o usuario)

Cliente

public  class Cliente {
    private SocketConnection client;
    private DataInputStream  input;
    private DataOutputStream  output;

    private String ipServidor;
      
    public synchronized void StartSocket(final String ip){
        new Thread(){
            public void run(){
                try {
                    client = (SocketConnection) Connector.open("socket://"+ip+":22285",Connector.READ_WRITE);
                    output = client.openDataOutputStream();
                    input = client.openDataInputStream();
                    client.setSocketOption(client.KEEPALIVE, 1);

                } catch (Exception ex) {
                    System.out.println("erro na conexão ao servidor: "+ex.toString() + " + "+ ex.getMessage());
                }
            }
        }.start();
    }

   ////// PONTO 2 - Se eu deixo linha do this.output.close; habilitada ele faz o envio e recebimento correto da mensagem, mas fecha o output, que eu não quero, porque depois eu quero enviar um arquivo pelo mesmo output
////// se eu deixo  a linha do this.output.close ; comentada, ele trava no "PONTO 1" como comentei ali em cima e fica travado.

public synchronized void enviarMensagem(String mensagem) throws IOException {
      
     this.output.write(mensagem.getBytes(),0, mensagem.length());

     this.output.flush();
     this.output.close();        // <<<<< AQUI
     //this.mensagem = null;
    }

Comentei no código, o PONTO 1 e PONTO 2.

No método aonde eu vou enviar o arquivo, APÓS esta mensagem está assim:

 public synchronized  void enviaLista(String arquivoCliente) {
      try {
            this.output = new DataOutputStream(client.openDataOutputStream());

         //this.output = client.openDataOutputStream();

         FileConnection fcup = (FileConnection)Connector.open(arquivoCliente, Connector.READ);

         input = fcup.openDataInputStream();
        
         byte[] buffer = new byte[512];
         int readed = -1;
         while ((readed = input.read(buffer))!= -1){
            output.write(buffer); //,0,readed);
         }
         output.flush();
         ///////client.close();
      } catch (IOException ex) {
         //System.out.println("Erro no envio da lista ao servidor: "+ex.toString() + " + "+ ex.getMessage());
         ex.printStackTrace();
      }
   }

Nas duas primeiras linhas do metodo enviaLista, eu tento “abrir” um novo DataOutputStream, mas qualquer uma das duas linhas, levanta a exceção:
java.io.IOException: no more output streams available

Alguém tem alguma ideia? Já revirei por tudo e não dá jeito. :cry:

[/quote]