@Override
    public void run() {
      while (!close.get()) {
        byte[] buffer = new byte[Pacote.default_size];
        DatagramPacket packet = new DatagramPacket(buffer, Pacote.default_size);

        try {
          real_socket.receive(packet); // recebe um pacote

          int key = OperacoesBinarias.extrairNumeroReconhecimento(buffer);
          int seqNum = OperacoesBinarias.extrairNumeroSequencia(buffer);
          int dataLength = OperacoesBinarias.extrairComprimentoDados(buffer);

          if (OperacoesBinarias.extrairFIN(buffer)) {
            if (arquivo_enviar != null) {
              arquivo_enviar.close();
            }

            if (arquivo_receber != null) {
              arquivo_receber.close();
            }
            close.set(true);
            miniSocket.this.close();
          } else if (OperacoesBinarias.extrairSYN(buffer)) {

          } else if (OperacoesBinarias.extrairACK(buffer)) {

            if (packet.getAddress().equals(client_adress)
                && packet.getPort() == client_port) { // tenho um ack de quem me comunico

              Pacote temp = null;

              synchronized (sinc_send_buffer) {
                int remap = key - send_packets_cont.get();

                if ((remap) < send_packet_buffer.size()
                    && !send_packet_buffer.isEmpty()
                    && remap
                        >= 0) { // verifica se o pacote esta dentro das possibilidades do buffer

                  temp = send_packet_buffer.get(remap);

                  temp_SampleRTT.set(
                      System.currentTimeMillis()
                          - temp.send_time); // atualiza variavel com sampleRTT temporário

                  if (!temp.isEnviado()) {
                    temp.setEnviado(true);
                    cwin.set(Math.min(cwin.get() + 10, max_win));
                  }
                }
              }

              if (key > estimateRTT_for_packet.get() && estimateRTT_process.get() && temp != null) {
                long temp_SampleRTT =
                    System.currentTimeMillis() - temp.send_time; // Calculo sampleRTT
                EstimatedRTT =
                    (long)
                        ((EstimatedRTT * 0.875)
                            + (0.125 * temp_SampleRTT)); // Use para Estimar o proximoRTT
                DevRTT =
                    (long)
                        ((0.75 * DevRTT)
                            + (0.25
                                * Math.abs(temp_SampleRTT - EstimatedRTT))); // E também o DevRTT
                timeout.set(EstimatedRTT + (4 * DevRTT)); // E altere o timeout
                estimateRTT_process.set(false);
              }

            } else {
              System.out.println(
                  "Recebi um ACK de um host estranho. Cuidado a rede pode estar sendo invadida!");
            }

          } else if (OperacoesBinarias.extrairRST(buffer)) {
            arquivo_receber.close();

          } else { // temos um pacote com dados

            if (packet.getAddress().equals(server_adress)
                && packet.getPort() == server_port) { // tenho um ack de quem me comunico
              byte[] to_ack = new byte[Pacote.head_payload];
              OperacoesBinarias.inserirCabecalho(
                  to_ack, 0, seqNum, true, false, false, false, 0, rcv_base.get() + rwin.get());
              DatagramPacket ack =
                  new DatagramPacket(to_ack, Pacote.head_payload, server_adress, server_port);
              synchronized (sinc_send_socket) { // envia ack
                real_socket.send(ack);
              }

              if (seqNum == rcv_base.get()) { // se temos o proximo pacote esperado
                arquivo_receber.write(
                    buffer, Pacote.head_payload, dataLength); // escreve para camada de cima
                rcv_base.incrementAndGet(); // incrementa a base da janela
                //								velocidade.getAndAdd(dataLength);
                last_receiverd += dataLength;

                // tenta pegar mais pacotes que possa estar no buffer de recepção
                while (rec_packet_buffer.get(rcv_base.get()) != null) {
                  byte[] dados = rec_packet_buffer.get(rcv_base.get());
                  dataLength = OperacoesBinarias.extrairComprimentoDados(dados);
                  //									velocidade.getAndAdd(dataLength);
                  last_receiverd += dataLength;
                  rcv_base.incrementAndGet(); // incrementa a base de recepção para o proximo pacote
                  arquivo_receber.write(dados, Pacote.head_payload, dataLength);
                }

              } else if (seqNum > rcv_base.get()) { // se não temos o proximo pacote esperado
                // coloca ele no buffer
                rec_packet_buffer.put(seqNum, buffer);
              } else {
                System.out.println("Retransmissao");
              }
            }
          }
        } catch (IOException e) {
          System.out.println("Deu merda no Socket do receiver fechando conexão...");
          close.set(true);
        }
      }
      System.out.println("Receiver Encerrado...");
    }