Socket- does not receive the message in full

Asked

Viewed 71 times

3

I have these codes: I’m still doing tests...

Client system:

private void btComunicarActionPerformed(java.awt.event.ActionEvent evt) {                                            
        List<PessoaMOD> pessoas = new ArrayList<PessoaMOD>();

        for (int i = 1; i <= 400; i++) {
            pessoas.add(new PessoaMOD(i,
                    "Pessoa " + i,
                    "111.111.111.11",
                    "11.111.111-1",
                    "Rua Violetas " + i,
                    "Numero " + i,
                    "Complemento " + i,
                    "Bairro " + i,
                    "Cidade " + i,
                    "Estado" + i,
                    "Telefone 1" + i,
                    "Telefone 2" + i,
                    "Email" + i,
                    'f'));
        }

        try {
            Socket cliente = new Socket("127.0.0.1", 12345);
            enviarMensagem(serializarPessoa(pessoas), cliente);
            cliente.close();
        } catch (Exception e) {
            System.out.println("Erro: " + e.getMessage());
        } finally {
        }
    }                                           

    public byte[] serializarPessoa(List<PessoaMOD> pessoas) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(bos);
        dos.writeInt(pessoas.size()); // tamanho da lista
        int cont = 0;
        for (PessoaMOD p : pessoas) {
            dos.writeInt(p.getId()); // id da pessoa
            dos.writeUTF(p.getNome());
            dos.writeUTF(p.getCpf());
            dos.writeUTF(p.getRg());
            dos.writeUTF(p.getEndereco());
            dos.writeUTF(p.getNumero());
            dos.writeUTF(p.getComplemento());
            dos.writeUTF(p.getBairro());
            dos.writeUTF(p.getCidade());
            dos.writeUTF(p.getEstado());
            dos.writeUTF(p.getTelefone1());
            dos.writeUTF(p.getTelefone2());
            dos.writeUTF(p.getEmail());
            dos.writeChar(p.getPerfil());//Nome da pessoa
        }
        return bos.toByteArray();
    }

    public void enviarMensagem(byte[] mensagem, Socket socket) throws IOException {
        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
        System.out.println("Lenght: " + mensagem.length);
        out.writeInt(mensagem.length); //O tamanho da mensagem
        out.write(mensagem); //Os dados
        out.flush();
        out.close();
    }

Server system:

private void btIniciarActionPerformed(java.awt.event.ActionEvent evt) {                                          
        new Thread() {
            @Override
            public void run() {
                try {
                    ServerSocket servidor = new ServerSocket(12345);
                    System.out.println("Servidor ouvindo a porta 12345");
                    while (true) {
                        Socket cliente = servidor.accept();
                        DataInputStream entrada = new DataInputStream(cliente.getInputStream());

                        int tamanhoMsg = entrada.readInt();
                        System.out.println("Tam. Msg.: " + tamanhoMsg);

                        byte[] bytes = new byte[tamanhoMsg];
                        entrada.read(bytes, 0 , bytes.length);
                        System.out.println("Bytes size: " + bytes.length);

                        DataInputStream entrada2 = new DataInputStream(new ByteArrayInputStream(bytes));

                        int tamanhoLista = entrada2.readInt();

                        int id;
                        String nome;
                        String cpf;
                        String rg;
                        String endereco;
                        String numero;
                        String complemento;
                        String bairro;
                        String cidade;
                        String estado;
                        String telefone1;
                        String telefone2;
                        String email;
                        char perfil;

                        for (int i = 0; i < tamanhoLista; i++) {
                            id = entrada2.readInt();
                            nome = entrada2.readUTF();
                            cpf = entrada2.readUTF();
                            rg = entrada2.readUTF();
                            endereco = entrada2.readUTF();
                            numero = entrada2.readUTF();
                            complemento = entrada2.readUTF();
                            bairro = entrada2.readUTF();
                            cidade = entrada2.readUTF();
                            estado = entrada2.readUTF();
                            telefone1 = entrada2.readUTF();
                            telefone2 = entrada2.readUTF();
                            email = entrada2.readUTF();
                            perfil = entrada2.readChar();

                            System.out.println("Id: " + id);
                            System.out.println("Nome: " + nome);
                            System.out.println("Cpf: " + cpf);
                            System.out.println("Rg: " + rg);
                            System.out.println("Endereço: " + endereco);
                            System.out.println("Número: " + numero);
                            System.out.println("Complemento: " + complemento);
                            System.out.println("Bairro: " + bairro);
                            System.out.println("Cidade: " + cidade);
                            System.out.println("Estado: " + estado);
                            System.out.println("Telefone 1: " + telefone1);
                            System.out.println("Telefone 2: " + telefone2);
                            System.out.println("Email: " + email);
                            System.out.println("Perfil: " + perfil);
                            System.out.println("");
                        }
                        entrada.close();
                        entrada2.close();
                        cliente.close();
                    }
                } catch (Exception e) {
                    System.out.println("Erro: " + e.getMessage());
                } finally {
                }
            }
        }.start();
    }    

It happens that the message does not come complete, it has time that I execute and the list comes to the person 37, sometimes to the person 392, each hour comes a lot of person from the list...

The variable of message size and that of list size are coming right...

2 answers

3

You are calling input.read() only once. In this case it will not wait until it has enough bytes to fill the buffer; it will return as soon as it has something received, even if it is 1 byte. If it returns 0 bytes it is because the connection was interrupted. While the connection exists read() waits. Typically it will deliver, at each return, what fits in a TCP package, whose size varies from 60 to 1400 bytes.

The solution is to loop and call read() several times until you have read the expected amount of bytes (and treat the case of receiving 0 bytes)

3

As @epx has already mentioned, data is transmitted over the network in blocks, so you need a loop to recompose the data blocks until the expected total amount of bytes is received.

An advantage of using serialization with ObjectOutputStream and ObjectInputStream is that these classes already have the control necessary to send and read the correct amount of bytes.

To solve the problem in your case, without using other classes, you can use the method readFully() that already contains the loop. Example:

entrada.readFully(bytes);

For you to get an idea of what it does, the implementation of the method that actually runs is like this:

public final void readFully(byte b[], int off, int len) throws IOException {
    if (len < 0)
        throw new IndexOutOfBoundsException();
    int n = 0;
    while (n < len) {
        int count = in.read(b, off + n, len - n);
        if (count < 0)
            throw new EOFException();
        n += count;
    }
}
  • Surely this is the ideal answer

Browser other questions tagged

You are not signed in. Login or sign up in order to post.