Problema com escrever bytes no socket... (RESOLVIDO UHULL)

14 respostas
dedspr

Olá Pessoal, estou com um problema na minha aplicação com socket…

Eu retorno do socket para o cliente um XML, no qual primeiramente escreve a quantidade de bytes que será escrito e escreve o XML em bytes da seguinte forma

//STRING COM MEU XML
String xmlOutput = "MEU_XML";

//ESCREVE O CÓDIGO DA OPERAÇÃO PARA DIZER QUE RECEBEREI UM XML
this.saida.writeInt(0);

//ESCREVE O TAMANHO DO XML
this.saida.writeInt(xmlOutput.length());

//ESCREVO OS BYTES
this.saida.write(xmlOutput.getBytes());

No lado do cliente pego da seguinte maneira…

if(!socketCliente.isClosed())
{
          //PEGO O TAMANHO DO XML
          int tam = this.entrada.readInt();

          //CRIO OS BYTES DELE
          byte[] b = new byte[tam];
          this.entrada.read(b, 0, tam);

          //RETURNO TRANSFORMANDO EM UMA STRING
          return new String(b);
}

Porém esta acontecendo uma coisa meio estranha… quando eu mando o socket escrever o tamanho do XML ele escreve certo… digamos que (400 bytes), mas quando pego no cliente ele pega números absurdos tipo ([telefone removido] bytes) dae estora o pau de java heap space…

Alguém sabe o porque deste erro… já debuguei o código e no socket server ele escreve certo… somente no cliente que pega este número absurdo…

14 Respostas

dedspr

Loucura… loucura, ninguém sabe…

KWill

Hmm, pode ser que você esteja esquecendo de “consumir” o tal código de operação… é a minha suspeita mais forte no momento.

Inté.

dedspr

KWill…

O código da operação eu consumo… uso ele verificar se vou pegar String ou Bytes…
E outra coisa se eu tivesse pegando ele ao invés do tamanho do bytes ele tinha que me retornar 0 não [telefone removido]

ViniGodoy

O retorno do read diz quantos bytes foram lidos. Quanto ele está retornando? tam bytes?

Que eu me lembre, não é garantido que o método read bloqueie até que a leitura de todos os bytes termine.

dedspr

Então ViniGodoy…

Ele está retornando um batalhão de bytes… retorno [telefone removido] bytes… e estora o java heap space…

Estou com a impressão que esta com erro no escrever, não sei a saida ficar acumulando os dados, por eu coloquei um string “Teste” para retornar mas mesmo assim não funcionou…

ViniGodoy

Como a variável entrada foi declarada?

Eu geralmente uso os Sockets através da classe SocketChannel e leio usando ByteBuffers. Aí esse tipo de problema não acontece.

dedspr

Bom a estrutura do meu socket server esta mais ou menos assim…

/*
 * ServidorThread.java
 *
 * Created on 8 de Agosto de 2008, 16:33
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

/*AQUI TEM OS IMPORTS*/

/**
 * Thread para os clientes que se conectam no socket
 * @author Douglas Emanoel
 */
public class ServidorThread extends Thread {
    
    private Socket socket;
    private DataInputStream entrada;
    private DataOutputStream saida;    
    private Sessao sessao;
    public ServidorThread(Socket socket, Sessao sessao)
    {
            try
            {
                    this.socket = socket;
                    this.entrada = new DataInputStream(this.socket.getInputStream());
                    this.saida = new DataOutputStream(this.socket.getOutputStream());
                    this.sessao = sessao;
            }
            catch(IOException ex)
            {
                    Servidor.debug("Não foi possivel criar a thread: " + ex.getMessage(), 1);
                    ex.printStackTrace();
            }
    }
    
    @Override
    public void run()
    {
            try
            {
                    //recebe o elemento e verifica a ação
                    String xmlOutput = "";
                    String[][] dadosXML = null;
                    int tipoRecebimento = this.lerInt();
                    String xmlRecebido = this.ler();
                    
                    //retorna os dados do usuario
                    this.usuarioPojo = usuarioBean.getDadosLogin(xmlRecebido);
                    
                    //efetua o login do usuario
                    String[][] usuarioArray = this.usuarioDAO.loginUsuario(this.usuarioPojo);
                    
                    if (usuarioArray[0][1].equals("erro_login") || usuarioArray[0][1].equals("erro_usuario_logado"))
                    {
                            this.saida.writeInt(0);
                            this.saida.writeInt(usuarioArray[0][1].length());
                            this.saida.write(usuarioArray[0][1].getBytes());
                            
                            this.stop();
                            this.interrupt();
                    }
                    else
                    {
                    
                            //seta o ID do grupo
                            this.usuarioPojo.setIDGrupo(Integer.parseInt(usuarioArray[2][1]));
                            this.usuarioPojo.setIDUsuario(Integer.parseInt(usuarioArray[0][1]));
                            this.usuarioPojo.setNMUsuario(usuarioArray[1][1]);
                            this.usuarioPojo.setSTUsuario(usuarioArray[3][1]);

                            // Aramazenando dados na classe
                            this.sessao.push(Integer.parseInt(usuarioArray[0][1]), "C", this.socket, this.entrada, this.saida);

                            while(true)
                            {
                                    try
                                    {
                                            if (xmlSocket.retornaAcaoXML(xmlRecebido).equals("inicia_sessao"))
                                            {
                                                    //ESCREVE OS DADOS PARA MIM
                                                    Vector vectorMSGOffline = this.sessaoDAO.getSessao(usuarioPojo);

                                                    if (vectorMSGOffline.size() > 0)
                                                    {
                                                            //GERA O XML DOS OPERADORES
                                                            xmlOutput = this.xmlSocket.geraXMLSocketVector("inicia_sessao", vectorMSGOffline, "msg", xmlOutput);

                                                            for (int x=0; x<vectorMSGOffline.size(); x++)
                                                            {
                                                                    String[][] resultadoLinha = (String[][])vectorMSGOffline.get(x);
                                                                    this.sessaoDAO.insereUsuarioXMensagemChat(this.usuarioPojo.getIDUsuario(), resultadoLinha[7][1]);
                                                            }

                                                            this.saida.writeInt(0);
                                                            this.saida.writeInt(xmlOutput.length());
                                                            this.saida.write(xmlOutput.getBytes());
                                                    }

                                                    this.atendimentoThread = new AtendimentoThread(this.saida, this.conexaoAtiva, this.usuarioPojo);
                                                    this.atendimentoThread.start();

                                                    /*this.agendaThread = new AgendaThread(this.saida, this.conexaoAtiva, this.usuarioPojo);
                                                    this.agendaThread.start();

                                                    this.atendimentoThreadWeb = new AtendimentoWebThread(this.saida, this.conexaoAtiva, this.usuarioPojo);
                                                    this.atendimentoThreadWeb.start();*/
                                            }
                                           else
                                            if (xmlSocket.retornaAcaoXML(xmlRecebido).equals("inicia_sessao_chat"))
                                            {
                                                    //AQUI É O LUGAR ONDE ACONTECE O ERRO
                                                    //ESCREVE OS DADOS PARA MIM
                                                    //String xmlSaida = this.xmlSocket.geraXMLSocket("inicia_sessao_chat", this.sessaoDAO.iniciaSessaoChat(this.sessaoBean.getDadosIniciaSessao(xmlRecebido)), "sessao");
                                                    /*String xmlSaida = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> "+
                                                                        "<pureComunicador tipo=\"inicia_sessao_chat\"> "+
                                                                        "     <sessao> "+
                                                                        "          <id_sessao_chat>352</id_sessao_chat> "+
                                                                        "          <tp_sessao_chat>C</tp_sessao_chat> "+
                                                                        "          <id_usuario>3</id_usuario> "+
                                                                        "          <id_usuario_conversa>52</id_usuario_conversa> "+
                                                                        "          <nm_usuario>AAAAAA</nm_usuario> "+
                                                                        "          <status>N</status> "+
                                                                        "     </sessao> "+
                                                                        "</pureComunicador>";*/

                                                    String xmlSaida = "Teste";

                                                    //FAZ A SESSÃO PARA MIM
                                                    this.saida.writeInt(0);

                                                    this.saida.writeInt(xmlSaida.length());
                                                    this.saida.writeBytes(xmlSaida);
                                            }
                                            /***AQUI TEM OUTRAS OPERAÇÕES PARA FUNCIONAR O SISTEMA****//



                                            //PEGA O QUE VEM DO CLIENTE
                                            tipoRecebimento = lerInt();
                                            if (tipoRecebimento == 0)
                                            {
                                                    xmlRecebido = null;
                                                    xmlRecebido = ler();
                                            }
                                            else
                                            {
                                                    //leio que é envio de arquivos
                                            }

                                            //CARA FOI DESCONECTADO
                                            if (xmlRecebido.equals(""))
                                            {
                                                    //ELIMINA O STATUS DO USUÁRIO
                                                    this.usuarioPojo.setSTOnline("N");
                                                    this.usuarioDAO.setStatusUsuario(this.usuarioPojo);

                                                    //ENVIA MSG PARA TODOS QUE ELE ESTA OFFLINE
                                                    xmlOutput = this.xmlSocket.geraXMLSocket("status_operador", this.usuarioBean.geraXMLStatus(this.usuarioPojo), "status");

                                                    // EXECUTA AS AÇÕES
                                                    for(int i = 0; i < sessao.length(); i++)
                                                    {
                                                            //ESCREVE PARA TODOS QUE FIQUEI ONLINE
                                                            if(sessao.arraySocket[i] != this.socket)
                                                            {
                                                                    sessao.arrayOut[i].writeInt(0);
                                                                    sessao.arrayOut[i].writeInt(xmlOutput.length());
                                                                    sessao.arrayOut[i].write(xmlOutput.getBytes());
                                                            }
                                                    }

                                                    sessao.pop(usuarioPojo.getIDUsuario(), "C", this.socket);

                                                    break;
                                            }

                                            this.saida.flush();
                                    }
                                    catch(Exception ex)
                                    {
                                            Servidor.debug("Erro ao receber mensagem...\nErro: " + ex.getMessage(), 1);
                                            ex.printStackTrace();
                                            // Fecha a conexão
                                            break;
                                    }

                            }

                            this.socket.close();
                            Servidor.debug("Conexão encerrada.", 2);

                    }
            }
            catch(Exception ex)
            {
                    Servidor.debug("Erro ocorrido: " + ex.getMessage(), 1);
                    ex.printStackTrace();
            }       

    }
    
    private String ler()
    {
            
            try
            {
                int tam = this.entrada.readInt();

                byte[] b = new byte[tam];
                entrada.read(b, 0, tam);

                return new String(b);
            }
            catch(Exception e)
            {
                //
            }
            
            return "";
    }
    
    private int lerInt()
    {
            
            try
            {
                int numero = this.entrada.readInt();

                return numero;
            }
            catch(Exception e)
            {
                //
            }
            
            return 0;
    }
    
    private byte[] lerByte()
    {
            
            try
            {
                int tam = this.entrada.readInt();

                byte[] b = new byte[tam];
                entrada.read(b, 0, tam);

                return b;
            }
            catch(Exception e)
            {
                //
            }
            
            return null;
    }
    
}

e o meu cliente socket é assim

/*
 * ClienteSocket.java
 *
 * Created on 30 de Julho de 2008, 16:27
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;


/**
 *
 * @author Douglas
 */
public class ClienteSocket {
    
    /**
     * Resource do socket
     */
    public Socket socketCliente;
    public DataInputStream entrada = null;
    public DataOutputStream saida = null;
    
    /**
     * Classe construtora do cliente socket
     * @param String endereço IP do socket server
     * @param int porta Número da porta do socket server
     * @param int id ID da sessão que o cliente está se conectando
     */
    public ClienteSocket(String endereco, int porta)
    {
            try 
            {
                    InetAddress address = InetAddress.getByName(endereco);
                    // Establish a socket connetion
                    socketCliente = new Socket(address, porta);
                    socketCliente.setKeepAlive(true);
                    socketCliente.setTcpNoDelay(true);
                    socketCliente.setPerformancePreferences(10,11,11);
                    socketCliente.setReceiveBufferSize(50000);
                    socketCliente.setSendBufferSize(50000);
                    socketCliente.setTrafficClass(255);
                    
                    this.entrada = new DataInputStream(socketCliente.getInputStream());
                    this.saida = new DataOutputStream(socketCliente.getOutputStream());
                    
                    // Setando o ID da conexão
                    //escreverSocket("ID:" + id);
            }
            catch (UnknownHostException ex) 
            {
                    ex.printStackTrace();
            }
            catch (IOException ex) 
            {
                    ex.printStackTrace();
            }
    }
    
    /**
     * Destrói a conexão com um socket
     * @return void
     */
    public void destroiSocket()
    {
            try 
            {
                    if(socketCliente.isConnected())
                    {
                            socketCliente.close();
                    }
            } 
            catch (IOException ex) 
            {
                    ex.printStackTrace();
            }
    }
    
    /**
     * Escreve em um socket
     * @param String texto Mensagem a ser enviada para o socket
     * @return void
     */
    public void escreverSocket(String texto)
    {
            try 
            {
                    if(socketCliente.isConnected())
                    {
                            this.saida.writeInt(0);
                            this.saida.writeInt(texto.length());
                            this.saida.write(texto.getBytes());
                            
                            this.saida.flush();
                    }
            } 
            catch (IOException er) 
            {
                    //PureScreen.debug("Erro ao escrever no socket.\nErro: " + er.getMessage(),1);
            }  
    }
    
    /**
     * Escreve em um socket
     * @param String texto Mensagem a ser enviada para o socket
     * @return void
     */
    public void escreverStringSocket(String texto)
    {

            try 
            {
                    if(socketCliente.isConnected())
                    {
                            this.saida.writeInt(texto.length());
                            this.saida.write(texto.getBytes());
                            
                            this.saida.flush();
                    }
            } 
            catch (IOException er) 
            {
                    //PureScreen.debug("Erro ao escrever no socket.\nErro: " + er.getMessage(),1);
            }  
    }
    
    public void escreverSocketByte(byte[] byteArray, int nbyteLido)
    {

            try 
            {
                    if(socketCliente.isConnected())
                    {
                            this.saida.write(byteArray, 0, nbyteLido);
                            
                            this.saida.flush();
                    }
            } 
            catch (IOException er) 
            {
                    //PureScreen.debug("Erro ao escrever no socket.\nErro: " + er.getMessage(),1);
            }  

    }
    
    public void escreverSocketInt(int escrever)
    {

            try 
            {
                    if(socketCliente.isConnected())
                    {
                            this.saida.writeInt(escrever);
                            
                            this.saida.flush();
                    }
            } 
            catch (IOException er) 
            {
                    //PureScreen.debug("Erro ao escrever no socket.\nErro: " + er.getMessage(),1);
            }  

    }
    
    /**
     * Faz a leitura de um socket
     * @return String
     */
    public String lerSocket()
    {
            try
            {
                    if(!socketCliente.isClosed())
                    {
                            int tam = this.entrada.readInt();
System.out.println(tam);
                            byte[] b = new byte[tam];
                            this.entrada.read(b, 0, tam);
System.out.println(new String(b));
                            return new String(b);
                            
                            
                    }
            } 
            catch (IOException f) 
            {
                    //PureScreen.debug("Erro ao fazer leitura do socket.\nErro: " + f.getMessage(),1);
            }
            catch (Exception g) 
            {
                    //PureScreen.debug("Erro ao fazer leitura do socket.\nErro: " + g.getMessage(),1);
            }
        
            return "";
    }
    
    public byte[] lerSocketByte()
    {
            try
            {
                    if(!socketCliente.isClosed())
                    {
                            int terminou = this.entrada.readInt();
                            
                            if (terminou == 0)
                            {
                                    int tam = this.entrada.readInt();
                                    byte[] b = new byte[tam];
                                    this.entrada.read(b, 0, tam);
                                    return b;
                            }
                            else
                            {
                                    return null;
                            }
                    }
            } 
            catch (IOException f) 
            {
                    //PureScreen.debug("Erro ao fazer leitura do socket.\nErro: " + f.getMessage(),1);
            }
            catch (Exception g) 
            {
                    //PureScreen.debug("Erro ao fazer leitura do socket.\nErro: " + g.getMessage(),1);
            }
        
            return null;
    }   
    
    public int lerSocketInt()
    {
            try
            {
                    if(!socketCliente.isClosed())
                    {
                            int dado = this.entrada.readInt();
                            
                            return dado;
                    }
            } 
            catch (IOException f) 
            {
                    //PureScreen.debug("Erro ao fazer leitura do socket.\nErro: " + f.getMessage(),1);
            }
            catch (Exception g) 
            {
                    //PureScreen.debug("Erro ao fazer leitura do socket.\nErro: " + g.getMessage(),1);
            }
        
            return 0;
    }   
    
    public boolean verificaConexao()
    {
            boolean conectado = false;
            
            try
            {
                    if(socketCliente.isConnected())
                    {
                            conectado = true;
                    }
            }
            catch (Exception g) 
            {
                    //PureScreen.debug("Erro ao fazer leitura do socket.\nErro: " + g.getMessage(),1);
            }
        
            return conectado;
    } 
}

Mais ou menos esse é meu código…
ViniGodoy você acha melhor fazer do teu jeito, poderia me mandar um exemplo do socket server e cliente?

T

Nem li o seu código, mas você não pode estar com algum problema do tipo “o que você espera ler de um lado não é a mesma coisa que você escreveu do outro lado”, porque, por exemplo, você se esqueceu de escrever algum dado?

Veja (talvez usando um debugger) se você está casando corretamente as escritas com as leituras.

T

E outra coisa que pode estar dando pau, que acho que é o mais provável.

É o seguinte: quando você converte uma string para um array de bytes, você tem de mandar o comprimento do array de bytes, não o comprimento original da string, porque se você estiver usando a codificação UTF-8 (que é a padrão no Linux mas não é a padrão no Windows), um caracter acentuado pode ser transformado em 2 bytes.

Ou seja (estou escrevendo um esboço, só para você ter uma idéia. Complete adequadamente)

writeInt (0)
byte[] dados = xml.getBytes("UTF-8")
writeInt (dados.length)
write (dados, 0, dados.length)
dedspr

Thingol…

O meu problema é o seguinte eu mando escrever um tanto de bytes no servidor, mas no cliente pela um numero impossivel de bytes…

Abaixo tem uma figura do tanto de bytes que ele busca…
Também coloque io codigo da forma que me falou, com o lenght ddo byte da imagem, mas mesmo assim continua com o erro


dedspr

Consegui identificar mais uma coisinha…

Acontece da seguinte maneira…
Se eu colocar par executar automaticamente a função ele retorna certo… mas se eu colocar para quando clicar ou na tecla pressionada ele da o erro…
Estou começando a crer que o erro esta no meu client…

dedspr

Alguém sabe se o socket tem algum tipo de cache…

dedspr

Pode ser que tenha alguma propriedade no meu socket que estou esquesendo de colocar… estou setando assim elas

this.socket.setKeepAlive(true);
this.socket.setTcpNoDelay(true);
this.socket.setPerformancePreferences(10,11,11);
this.socket.setReceiveBufferSize(50000);
this.socket.setSendBufferSize(50000);
this.entrada = new DataInputStream(this.socket.getInputStream());
this.saida = new DataOutputStream(this.socket.getOutputStream());
dedspr

OPlá pessoal… consegui resolver o problema… foi dificil mais arranquei metade do codigo e funcionou… agora estou colocando novamente

Criado 9 de setembro de 2008
Ultima resposta 10 de set. de 2008
Respostas 14
Participantes 4