diff --git a/headers/client.h b/headers/client.h
index 05638ffe61d6c30f17ad31fe40453cdd7ddcc14e..33bfd99517145bd3e2756aa4354a1b96a18b80e0 100644
--- a/headers/client.h
+++ b/headers/client.h
@@ -8,7 +8,6 @@
 #include <iostream>
 #include <linux/if.h>
 #include <linux/if_packet.h>
-#include <mutex>
 #include <net/ethernet.h>
 #include <netinet/in.h>
 #include <stdio.h>
@@ -23,6 +22,7 @@
 #include "conexao.h"
 #include "cores.h"
 #include "frame.h"
+
 using namespace std;
 
 class client {
@@ -41,11 +41,11 @@ private:
   bool string_has(string str, vector<string> strList);
   char string_cmd(string str);
   void print_help();
-  bool verify_ack(frame *received, frame *sent);
-  frame *receive_ack(frame *f);
+  bool verify_ack_nack(frame *received);
+  frame *receive_ack_nack();
   vector<frame *> create_frames(vector<char> data, int type);
   vector<frame *> create_frames_midia(vector<char> data);
-  int send_frame_socket(frame *f);
+  frame *send_frame_socket(frame *f);
   int start_transmission();
   int end_transmission();
   string calc_file_size(string fileName);
@@ -65,50 +65,53 @@ public:
 // ------------------------------ PRIVATE --------------------------------- //
 
 // Verifica se recebeu um ack valido
-frame *client::receive_ack(frame *f) {
-  frame *ack_res = NULL;
+frame *client::receive_ack_nack() {
+  frame *response = NULL;
 
   // se recebemos algo, e NÃO ẽ o ACK que estamos
   // esperando, continuamos tentando receber
   do {
-    ack_res = socket->receive_frame();
-    if (ack_res && ack_res->get_tipo() == ERRO) {
+    response = socket->receive_frame();
+    if (response && response->get_tipo() == ERRO) {
       cout << BOLDYELLOW << "Espaco insulficiente no destino\n" << RESET;
       return NULL;
     }
-  } while (ack_res &&
-           !(verify_ack(ack_res, f) && ack_res->get_dado()[0] == f->get_seq()));
+  } while (response && !(verify_ack_nack(response)));
 
-  return ack_res;
+  return response;
 }
 
 // Solicita ao socket que envie um frame
-int client::send_frame_socket(frame *f) {
+frame *client::send_frame_socket(frame *f) {
   // Fica tentando enviar o frame até receber o ack
-  frame *ack_res = NULL;
+  frame *response = new frame();
   int retries = 0;
   do {
     // envia um frame da fila
-    socket->send_frame(f);
-    ack_res = receive_ack(f);
+    int bytesSent = socket->send_frame(f);
+    if (bytesSent == -1) { return NULL; }
+
+    response = receive_ack_nack();
+    if (!response) return NULL;
     retries++;
-  } while (ack_res == NULL && retries < NUM_RETRIES);
+  } while (response->get_dado()[0] != f->get_seq() && retries < NUM_RETRIES);
 
-  if (ack_res == NULL && retries == NUM_RETRIES) {
-    // cout << "Desisti de enviar\n"; ->log
-    return 0;
+  if (response == NULL && retries == NUM_RETRIES) {
+    cout << "Desisti de enviar\n";
+    return NULL;
   }
 
-  // cout << "\tACK recebido:\n"; ->log
-  // ack_res->imprime(HEX);
-  return 1;
+  cout << "\tACK recebido:\n";
+  response->imprime(HEX);
+  return response;
 }
 
 // Inicia a transmissao com o servidor
 int client::start_transmission() {
   // cout<< YELLOW << "\tIniciando transmissao\n" << RESET; ->log
   frame *ini = new frame(INIT, 0, vector<char>(1, 0));
-  int enviado = send_frame_socket(ini);
+  frame *enviado = new frame();
+  enviado = send_frame_socket(ini);
   if (!enviado) {
     // cout<< BOLDRED << "\tFalha ao iniciar a transmissao\n" << RESET; ->log
     return 0;
@@ -122,7 +125,7 @@ int client::start_transmission() {
 int client::end_transmission() {
   // cout << "\tEncerrando a transmissao\n"; ->log
   frame *end = new frame(FIMT, 0, vector<char>(1, 0));
-  int enviado = send_frame_socket(end);
+  frame *enviado = send_frame_socket(end);
   if (!enviado) {
     // cout << "\tFalha ao encerrar a transmissao\n"; ->log
     return 0;
@@ -139,23 +142,68 @@ int client::end_transmission() {
  * @return int
  */
 int client::send_frames(vector<frame *> frames) {
+
   if (frames.empty()) { return 0; }
 
+  cout << "\tstart transmission\n";
   if (!start_transmission()) { return 0; }
+  cout << "\t ->>> started transmission <<< -\n";
 
-  // Envia um frame por vez
-  for (size_t i = 0; i < frames.size(); i++) {
+  // Cria a fila de frames
+  queue<int> janela;
+  int frameCounter;
+  int iniJanela = 0;
+  while (iniJanela < frames.size()) {
 
-    // cout << "\tEnviando frame\n"; ->log
-    // frames[i]->imprime(DEC);
+    // manda todos os frames de uma vez só
+    for (frameCounter = 0; frameCounter < TAM_JANELA; frameCounter++) {
+      if (iniJanela + frameCounter == frames.size()) { break; }
+      janela.push(frameCounter);
+
+      cout << "\tEnviando frame\n";
+      frames[iniJanela]->imprime(HEX);
+
+      if (socket->send_frame(frames[iniJanela + frameCounter]) == -1) {
+        cout << "Falha ao enviar o frame\n";
+        return 0;
+      }
+
+      cout << "\tFrame enviado com sucesso\n";
+    }
 
-    int enviado = send_frame_socket(frames[i]);
-    if (!enviado) {
-      // cout << "\tFalha ao enviar o frame\n"; ->log
-      return 0;
+    // Recebe a resposta do servidor
+    for (int i = 0; i < min((int)TAM_JANELA, (int)frames.size()); i++) {
+      frame *res = NULL;
+      int retries = 0;
+
+      do {
+        res = receive_ack_nack();
+        retries++;
+      } while (res == NULL && retries < NUM_RETRIES);
+
+      if (res == NULL && retries == NUM_RETRIES) { return 0; }
+
+      if (res->get_tipo() == NACK && res->get_dado()[0] == janela.front()) {
+        cout << "NACK " << (int)res->get_dado()[0] << " recebido\n";
+        iniJanela += res->get_dado()[0];
+        janela.pop();
+        break;
+      }
+
+      if (res->get_tipo() == ACK && res->get_dado()[0] == janela.front()) {
+        cout << "ACK " << (int)res->get_dado()[0] << " recebido\n";
+        iniJanela++;
+        janela.pop();
+      }
+
+      else {
+        i--;
+      }
     }
 
-    // cout << "\tFrame enviado com sucesso\n"; ->log
+    // apaga a janela
+    while (!janela.empty())
+      janela.pop();
   }
 
   if (!end_transmission()) { return 0; }
@@ -172,8 +220,9 @@ int client::send_frames(vector<frame *> frames) {
  * @return true
  * @return false
  */
-bool client::verify_ack(frame *received, frame *sent) {
-  return (received->get_tipo() == ACK && received->chk_crc8());
+bool client::verify_ack_nack(frame *received) {
+  return ((received->get_tipo() == ACK || received->get_tipo() == NACK) &&
+          received->chk_crc8());
 }
 
 /**
@@ -300,7 +349,7 @@ vector<frame *> client::create_frames_midia(vector<char> vectorName) {
 
   // Arruma a sequencia dos frames
   for (int i = 0; i < framesToSend.size(); i++)
-    framesToSend[i]->set_seq(i % 16);
+    framesToSend[i]->set_seq(i % TAM_JANELA);
 
   return framesToSend;
 }
diff --git a/headers/conexao.h b/headers/conexao.h
index 702e89f82e838a887b659cde9d2f0f2dfef873ab..2fcab792cefc8d421796b5278492c9df5abbe9a5 100644
--- a/headers/conexao.h
+++ b/headers/conexao.h
@@ -19,12 +19,12 @@
 #include <arpa/inet.h>
 
 // include local
-#include "frame.h"
 #include "cores.h"
+#include "frame.h"
 using namespace std;
 
-#define BYTE "%02x"
-#define NUM_RETRIES 100
+#define NUM_RETRIES 10
+#define TAM_JANELA 2
 
 class conexao {
 private:
@@ -89,10 +89,6 @@ frame *conexao::receive_frame() {
 
   do {
     byteRecv = recv(device, bufferReceived, sizeof(frame) * 2, 0);
-    //    for (int i = 0; i < byteRecv; i++) {
-    //      cout << hex << (int(bufferReceived[i])&0xff) << " ";
-    //    }
-    // cout << "\n";
     if ((byteRecv > 0) && (bufferReceived[0] == INI)) {
       frame *f = new frame;
       remove_escapes(bufferReceived, (char *)f);
@@ -116,12 +112,15 @@ int conexao::send_frame(frame *f) {
   int timeout = 0;
 
   int byteSend = send(device, bufferSend, sizeof(frame) * 2, 0);
-  // printf("send %d: ", byteSend);
-  // for (int i = 0; i < byteSend; i++) {
-  //   cout << hex << (int(bufferSend[i]) & 0xff) << " ";
-  // }
-  // cout << "\n";
-  // if (byteSend < 0) { cout << "Erro no sendto" << byteSend << "\n"; } ->log
+  printf("send %d: ", byteSend);
+  for (int i = 0; i < byteSend; i++) {
+    cout << hex << (int(bufferSend[i]) & 0xff) << " ";
+  }
+  cout << "\n";
+  if (byteSend < 0) {
+    cout << "Erro no sendto" << byteSend << "\n";
+    return -1;
+  }
 
   return byteSend;
 }
@@ -166,7 +165,7 @@ int conexao::ConexaoRawSocket(char *device) {
 
   soquete = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); /*cria socket*/
   if (soquete == -1) {
-    cout << BOLDRED <<"\tErro no Socket, verifique se voce eh root\n" << RESET;
+    cout << BOLDRED << "\tErro no Socket, verifique se voce eh root\n" << RESET;
     exit(-1);
   }
 
diff --git a/headers/macros.h b/headers/macros.h
index a936d2fd44134ddbf5398f985340968d5de3535f..57c4d1b865683cfea8b293c11ce6e34d8f292d04 100644
--- a/headers/macros.h
+++ b/headers/macros.h
@@ -3,6 +3,7 @@
 
 #define UC unsigned char
 #define UI unsigned int
+#define UL unsigned long
 
 // Macro que cria uma sequencia com o 1 deslocado "des" posicoes a direita
 #define MASKR(des) (1 << des)
diff --git a/headers/server.h b/headers/server.h
index 18a2854dcb8e99c34c769fcc5a32a12942b07528..09359aa1078628e02076e3b2b5fd0746c4422a14 100644
--- a/headers/server.h
+++ b/headers/server.h
@@ -21,9 +21,10 @@
 #include <sys/types.h>
 
 // include local
-#include "conexao.h"
 #include "cores.h"
 #include "frame.h"
+#include "macros.h"
+#include "conexao.h"
 
 #define FILE_DESTINATION "./received"
 
@@ -33,28 +34,34 @@ class server {
 
 private:
   // --------- Dados ---------- //
-  int soquete;
+  //int soquete;
+  int tipoReceivingFrames;
 
   conexao *socket;
 
-  vector<frame *> framesMidia;
+  //vector<frame *> framesMidia;
 
   // ---------- Funcoes -------- //
-  int send_nack(frame *fReceive);
-  int send_ack(frame *fReceive);
-  void send_confirm(frame *fReceive);
-  void receive_text(frame *f);
-  void receive_midia(frame *f);
+
+  frame*    create_ack_nack     (int tipo, int seq);
+  int       send_nack           (frame *fReceive);
+  int       send_ack            (frame *fReceive);
+  bool      verify_seq          (int seq, int lastSeq);
+  int       next_tipo_midia     (frame *f);
+  bool      create_received_dir ();
+  UL        chk_available_size  ();
+  int       receive_file_size   (frame *f);
+  string    create_file_destination(string fileName);
+  ofstream  create_file         (string fileName);
+  int       receive_midia       (frame *f);
+  //void send_confirm(frame *fReceive);
+  //void receive_text(frame *f);
+  //int receive_valid_frame(frame **f);
+  //int receive_file_data(string fileName);
+  //bool verify_crc8(frame *f);
   frame *receive_frame_socket();
-  int receive_valid_frame(frame **f);
-  unsigned long chk_available_size();
-  int receive_file_size(frame *f);
+  queue<frame *> receive_frames_window(int lastSeq);
   void start_receveing_message();
-  bool create_received_dir();
-  string receive_file_name();
-  int receive_file_data(string fileName);
-  bool verify_crc8(frame *f);
-  bool verify_seq(int seq, int lastSeq);
 
 public:
   // ------- Construtores ------ //
@@ -65,6 +72,27 @@ public:
 };
 
 // ------------------------------ PRIVATE --------------------------------- //
+/**
+ * @brief function that creates a nack or a nack 
+ *
+ * @param tipo ack or nack
+ * @param seq  ack or nack sequence number
+ * @return int
+ */
+
+frame *server::create_ack_nack(int tipo, int seq)
+{
+  vector<char> seq_char;
+  frame *f = new frame();
+
+  f->set_tipo(tipo);
+  vector<char> seq_v;
+  seq_v.push_back(char(seq));
+  f->set_dado(seq_v);
+
+  return f;
+}
+
 /**
  * @brief function that sends a ack frame to the target
  *
@@ -73,17 +101,16 @@ public:
  */
 int server::send_ack(frame *fReceive) {
 
-  frame *ack = new frame();
+  frame *ack = create_ack_nack(ACK, fReceive->get_seq());
 
-  ack->set_tipo(ACK);
-  vector<char> seq;
-  seq.push_back(char(fReceive->get_seq()));
-  ack->set_dado(seq);
-
-  int ackSent = 0;
-  ackSent = socket->send_frame(ack);
+  int ackSent = socket->send_frame(ack);
+  if ( ackSent == -1 ) 
+  { 
+    cout << "Falha ao enviar o ack\n";
+    return -1; 
+  }
 
-  // cout << "ACK enviado\n"; ->log
+  cout << "ACK " << (int) fReceive->get_seq() << " enviado\n";
 
   return ackSent;
 }
@@ -96,43 +123,68 @@ int server::send_ack(frame *fReceive) {
  */
 int server::send_nack(frame *fReceive) {
 
-  frame *nack = new frame();
+  frame *nack = create_ack_nack(NACK, fReceive->get_seq());
 
-  nack->set_tipo(NACK);
-  vector<char> seq;
-  seq.push_back(char(fReceive->get_seq()));
-  nack->set_dado(seq);
-
-  int nackSent = 0;
-  nackSent = socket->send_frame(nack);
+  int nackSent = socket->send_frame(nack);
+  if ( nackSent == -1 ) { 
+    cout << "Falha ao enviar o nack";
+    return -1; 
+  }
 
-  // cout << "NACK enviado\n"; ->log
+  cout << "NACK " << (int) fReceive->get_seq() << " enviado\n";
 
   return nackSent;
 }
 
-// Recebe uma mensagem em forma de texto
-void server::receive_text(frame *f) {
-  string textoReceive;
-  textoReceive.append(f->get_dado());
-  int lastSeq = f->get_seq();
+/**
+ * @brief function that verify if two numbers are sequential
+ *
+ * @param seq
+ * @param lastSeq
+ * @return bool 
+ */
+bool server::verify_seq(int seq, int lastSeq) {
+  if ( seq == 0 )
+  {
+    if ( lastSeq != 15 ) { return false; }
+    return true;
+  }
 
-  do {
-    if (!receive_valid_frame(&f)) { return; }
-    if (f->get_tipo() != TEXTO) { continue; }
-    if (f->get_seq() == lastSeq) { continue; }
+  if (seq != lastSeq + 1) { return false; }
+  return true;
+}
 
-    lastSeq = f->get_seq();
-    textoReceive.append(f->get_dado());
-  } while (f->get_tipo() != FIMT);
+int server::next_tipo_midia(frame *f) {
+  if ( f->get_tipo() != MIDIA ) { return -1; }
+  if ( f->get_seq() == 0 )      { return MIDIA; }
+  if ( f->get_seq() == 1 )      {
+    cout << YELLOW << "\t--Recebendo dados arquivo--\n" << RESET;
+    return DADOS; }
 
-  cout << BOLDYELLOW << "\t--Mensagem recebida--\n " << BOLDWHITE
-       << textoReceive << "\n"
-       << RESET;
+  return -1;
 }
 
-// Verifica o espaco disponivel em disco
-unsigned long server::chk_available_size() {
+//// Recebe uma mensagem em forma de texto
+//void server::receive_text(frame *f) {
+//  string textoReceive;
+//  textoReceive.append(f->get_dado());
+//  int lastSeq = f->get_seq();
+//
+//  do {
+//    if (!receive_valid_frame(&f)) { return; }
+//    if (f->get_tipo() != TEXTO) { continue; }
+//    if (f->get_seq() == lastSeq) { continue; }
+//
+//    lastSeq = f->get_seq();
+//    textoReceive.append(f->get_dado());
+//  } while (f->get_tipo() != FIMT);
+//
+//  cout << "Mensagem recebida: " << textoReceive << "\n";
+//}
+//
+//// Verifica o espaco disponivel em disco
+
+UL server::chk_available_size() {
   struct statvfs st;
   if (statvfs(FILE_DESTINATION, &st) == -1) {
     // cout << "Erro no statvfs, abortado\n";->log
@@ -143,47 +195,22 @@ unsigned long server::chk_available_size() {
   return st.f_bsize * st.f_bavail;
 }
 
-// Recebe o frame com o tamanho do arquivo
+//// Recebe o frame com o tamanho do arquivo
 int server::receive_file_size(frame *f) {
 
-  /*
-     > verifica a sequencia do frame e o tipo
-     > se o frame nao for a sequencia esperada, envia um ack(0) e espera receber
-     a sequencia esperada > se o frame for o esperado, verifica o crc8 > se o
-     crc estiver certo, envia um ack e continua > se estiver errado, envia um
-     nack e espera receber o proximo frame
-  */
-  // cout << "Recebendo tamanho do frame\n";->log
-  do {
-    if (f->get_tipo() != MIDIA) { continue; }
-    if (f->get_seq() == 0 && verify_crc8(f)) { break; }
-
-    if (f->get_seq() != 0)
-      cout << "Sequencia errada\n";
-    else
-      cout << "Crc errado\n";
-
-    cout << "Aguardando frame\n";
-
-    f = receive_frame_socket();
-    if (!f) { return 0; }
+ cout << "Recebendo tamanho do frame\n";
+ unsigned long availSize = chk_available_size();
+ if (availSize == -1) { return -1; }
 
-    cout << "Frame recebido\n";
+ cout << "Frame file size:" << f->get_dado() << "\n";
+ int fileSize = stoi(f->get_dado());
 
-  } while (true);
-
-  unsigned long availSize = chk_available_size();
-  if (availSize == -1) { return -1; }
-
-  // cout << "Frame file size:" << f->get_dado() << "\n"; ->log
-  int fileSize = stoi(f->get_dado());
-
-  if (fileSize > availSize * 0.9) {
+ if (fileSize > availSize * 0.9) {
     cout << BOLDMAGENTA << "\t--Tamanho do arquivo muito grande, abortado--\n"
          << RESET;
     // send_error();
     return 0;
-  }
+ }
 
   // cout << "Espaco suficiente em disco\n"; ->log
   return 1;
@@ -191,7 +218,8 @@ int server::receive_file_size(frame *f) {
 
 bool server::create_received_dir() {
 
-  // check if the directory exists
+  cout << "Criando diretorio";
+  // Check if the directory exists
   struct stat info;
   if (stat(FILE_DESTINATION, &info) == 0 && (info.st_mode & S_IFDIR)) {
     // cout << "Diretorio ja existe\n"; ->log
@@ -208,63 +236,67 @@ bool server::create_received_dir() {
   return true;
 }
 
-string server::receive_file_name() {
-  frame *fReceive;
-
-  // Aguarda receber um frame do tipo midia com o nome do arquivo
-  // E com a sequencia de numero 2
-  /*
-    > recebe o frame e verifica se o tipo e a sequencia estao corretos
-    > se estiverem, verifica o crc8
-    > se estiver correto, envia um ack e continua
-    > se estiver errado, envia um nack e espera receber o proximo frame
-  */
-  // cout << "Recebendo nome do arquivo\n";->log
-
-  do {
-    // cout << "Aguardando frame\n";->log
-    fReceive = receive_frame_socket();
-    if (!fReceive) { return string{}; }
-
-    // cout << "Frame recebido\n";->log
-
-    if (fReceive->get_tipo() != MIDIA) { continue; }
-    if (fReceive->get_seq() != 1) {
-      // cout << "Sequencia errada\n";->log
-      fReceive->set_seq(0);
-      send_ack(fReceive);
-      continue;
-    }
-
-    if (verify_crc8(fReceive)) { break; }
-
-    // cout << "Crc invalido, aguardando retransmissao\n"; ->log
-
-  } while (true);
-
-  // cout << "Nome do arquivo recebido com sucesso\n"; ->log
-  // cout << "Nome do arquivo: " << fReceive->get_dado() << "\n"; ->log
-
-  return string(fReceive->get_dado());
-}
-
-bool server::verify_seq(int seq, int lastSeq) {
-  // cout << "seq: " << seq << " lastSeq: " << dec << lastSeq << "\n"; ->log
-  if (seq == 0) {
-    if (lastSeq != 15) { return false; }
-    return true;
-  }
-
-  if (seq != lastSeq + 1) { return false; }
-  return true;
-}
-
-int server::receive_file_data(string fileName) {
+//int server::receive_file_data(string fileName) {
+//
+//  int lastSeq = 1;
+//  frame *f;
+//
+//  cout << "\tRecebendo dados arquivo\n";
+//  do {
+//    cout << "Aguardando frame\n";
+//
+//    // Fica tentando receber um frame
+//    f = receive_frame_socket();
+//    if (f == NULL) { return 0; }
+//
+//    cout << "Frame recebido\n";
+//    f->imprime(HEX);
+//
+//    if (f->get_tipo() == FIMT) { break; }
+//
+//    if (f->get_tipo() != DADOS) { continue; }
+//
+//    if (f->get_seq() == lastSeq) { continue; }
+//
+//    // Recebeu um frame com uma sequencia errada
+//    if (!verify_seq(f->get_seq(), lastSeq)) {
+//      cout << "Frame com a sequencia errada; Pedindo a certa\n";
+//      f->set_seq(lastSeq);
+//      send_ack(f);
+//      continue;
+//    }
+//
+//    if (!verify_crc8(f)) { 
+//      cout << "Crc invalido\n";
+//      continue; 
+//    }
+//
+//    cout << "Seq " << int(f->get_seq()) << "recebida com sucesso\n";
+//    lastSeq = f->get_seq();
+//    file.write(f->get_dado(), f->get_tam());
+//
+//  } while (true);
+//
+//  cout << "Dados do arquivo recebido com sucesso\n";
+//  send_ack(f);
+//
+//  file.close();
+//  return 1;
+//}
+//
+
+string server::create_file_destination(string fileName)
+{
   string fileDestination;
   fileDestination.append(FILE_DESTINATION);
   fileDestination.push_back('/');
   fileDestination.append(fileName);
 
+  return fileDestination;
+}
+
+ofstream server::create_file(string fileName) {
+  string fileDestination = create_file_destination(fileName);
 
   cout << BOLDWHITE << "Criando arquivo " << BOLDYELLOW << fileDestination
        << BOLDWHITE << ". Digite novo nome ou enter para continuar: " << RESET;
@@ -280,79 +312,46 @@ int server::receive_file_data(string fileName) {
   // Abre o arquivo para escrita
   ofstream file;
   file.open(fileDestination, ios::binary);
-  if (!file.is_open()) {
-    cout << RED << "\tFalha ao criar o arquivo. Abortado\n" << RESET;
-    return 0;
-  }
-
-  int lastSeq = 1;
-  frame *f;
-
-  cout << YELLOW << "\t--Recebendo dados arquivo--\n" << RESET;
-  do {
-    // Fica tentando receber um frame
-    f = receive_frame_socket();
-    if (f == NULL) {
-      // cout << BOLDRED << "\tErro ao receber dados do arquivo\n" << RESET;
-      // ->log
-      file.close();
-      remove(fileDestination.c_str());
-      return 0;
-    }
-
-    // f->imprime(HEX); ->log
-
-    if (f->get_tipo() == FIMT) { break; }
-
-    if (f->get_tipo() != DADOS) { continue; }
-
-    if (f->get_seq() == lastSeq) { continue; }
-
-    // Recebeu um frame com uma sequencia errada
-    if (!verify_seq(f->get_seq(), lastSeq)) {
-      // cout << "Frame com a sequencia errada; Pedindo a certa\n"; ->log
-      f->set_seq(lastSeq);
-      send_ack(f);
-      continue;
-    }
+  return file;
+}
 
-    if (!verify_crc8(f)) {
-      // cout << "Crc invalido\n"; ->log
-      continue;
-    }
+int server::receive_midia(frame *f) {
+  
+  ofstream file;
 
-    // cout << "Seq " << int(f->get_seq()) << "recebida com sucesso\n"; ->log
-    lastSeq = f->get_seq();
+  // Escreve o dado no arquivo
+  if ( f->get_tipo() == DADOS )
+  {
     file.write(f->get_dado(), f->get_tam());
+    return 1;
+  }
 
-  } while (true);
-
-  // cout << "\tDados do arquivo recebido com sucesso\n"; ->log
-  send_ack(f);
-
-  file.close();
-  return 1;
-}
-
-void server::receive_midia(frame *f) {
-  cout << BOLDYELLOW << "\t--Recebendo arquivo--\n" << RESET;
-  // cout << "Recebendo frame midia\n"; ->log
-  if (!create_received_dir()) { return; }
-  if (!receive_file_size(f)) { return; }
-
-  string fileName = receive_file_name();
+  // Primeiro frame de midia
+  if ( f->get_seq() == 0 )
+  {
+    cout << "Recebendo tamanho do arquivo\n";
+    if (!create_received_dir()) { return 0; }
+    if (!receive_file_size(f))  { return 0; }
+  }
 
-  if (fileName.size() == 0) { return; }
+  // Segundo frame de midia
+  string fileName = string(f->get_dado());
+  file = create_file(fileName);
 
-  if (!receive_file_data(fileName)) {
-    cout << BOLDRED << "\t--Falha ao receber o arquivo\n--" << RESET;
-    return;
+  if (!file.is_open())
+  {
+    cout << RED << "\tFalha ao criar o arquivo. Abortado\n" << RESET;
+    file.close();
+    remove(create_file_destination(fileName).c_str());
+    return 0;
   }
 
-  cout << BOLDGREEN << "\t--Arquivo recebido com sucesso--\n" << RESET;
+  // cout << BOLDGREEN << "\t--Arquivo recebido com sucesso--\n" << RESET;
+  if ( !file.is_open() )     { return 0; }
+  return 1;
 }
 
-// Recebe um frame do cliente
+//// Recebe um frame do cliente
 frame *server::receive_frame_socket() {
   frame *fReceive;
   int retries = 0;
@@ -369,54 +368,205 @@ frame *server::receive_frame_socket() {
 
   return fReceive;
 }
+//
+//bool server::verify_crc8(frame *f) {
+//  int crc8 = f->chk_crc8();
+//  if (!crc8) {
+//    send_nack(f);
+//  }
+//  else
+//    send_ack(f);
+//  return crc8;
+//}
+//
+//int server::receive_valid_frame(frame **f) {
+//
+//  do {
+//    // Se nao conseguir receber o frame, mata a comunicacao
+//    *f = receive_frame_socket();
+//    if (*f == NULL) { return 0; }
+//
+//    // Avisa o cliente se nao conseguiu receber o frame
+//  } while (!verify_crc8(*f));
+//  return 1;
+//}
+
+queue<frame *> server::receive_frames_window(int lastSeq)
+{
+  queue<frame *> frames_queue;
+  frame *f;
+  int retries = 0;
 
-bool server::verify_crc8(frame *f) {
-  int crc8 = f->chk_crc8();
-  if (!crc8) {
-    send_nack(f);
-  } else
-    send_ack(f);
-  return crc8;
-}
+  do {
+    if ( ! (f = receive_frame_socket()) ) { continue; }
+    
+    retries++;
 
-int server::receive_valid_frame(frame **f) {
+    int tipo = f->get_tipo();
 
-  do {
-    // Se nao conseguir receber o frame, mata a comunicacao
-    *f = receive_frame_socket();
-    if (*f == NULL) { return 0; }
+    // Adiciona o frame de fim de transmissao
+    if ( tipo == FIMT ) 
+    {
+      frames_queue.push(f);
+      return frames_queue;
+    }
 
-    // Avisa o cliente se nao conseguiu receber o frame
-  } while (!verify_crc8(*f));
-  return 1;
+    // Primeiro frame a ser recebido, seta o tipo
+    if ( lastSeq == -1 ) 
+    {
+      // Ignora os frames perdidos na linha
+      if ( (tipo != MIDIA && tipo != TEXTO) || f->get_seq() != 0 ) {continue;}
+      tipoReceivingFrames = f->get_tipo();
+      frames_queue.push(f);
+      lastSeq = 0;
+      retries = 0;
+      continue; 
+    }
+
+
+    // Ignora se o frame nao for do tipo midia e esteja recebendo midia
+    if ( tipo == MIDIA && tipoReceivingFrames == MIDIA )
+    {
+      // Ignora se for um frame do tipo midia que nao e o segundo da sequencia
+      if ( lastSeq != 0 || (TAM_JANELA > 1 && f->get_seq() != 1)) { continue; }
+
+      // Se for o segundo frame do tipo midia, muda o tipo esperado
+      tipoReceivingFrames = DADOS;
+      frames_queue.push(f);
+      lastSeq = 1;
+      retries = 0;
+      continue;
+    }
+
+    // Recebe os frames de dados de um arquivo
+    if ( tipoReceivingFrames == DADOS && tipo == DADOS )
+    {
+      if ( !verify_seq(f->get_seq(), lastSeq) ) { continue; }
+      frames_queue.push(f);
+      retries = 0;
+      lastSeq = f->get_seq();
+      continue;
+    }
+
+    // Recebe os frames de uma mensagem
+    if ( tipoReceivingFrames == TEXTO && tipo == TEXTO )
+    {
+      if ( !verify_seq(f->get_seq(), lastSeq) ) { continue; }
+      frames_queue.push(f);
+      retries = 0;
+      lastSeq = f->get_seq();
+      continue;
+    }
+
+  } while ( (f == NULL && retries < NUM_RETRIES) || frames_queue.size() < TAM_JANELA );
+
+  if ( f == NULL && retries == NUM_RETRIES ) { return queue<frame *>(); }
+
+  return frames_queue;
 }
 
 void server::start_receveing_message() {
   int continueTransmission = 1;
+  int lastSeq = -1;
+  int tipo_data = -1;
+  vector<char> data;
+  queue<frame *> client_answer;
 
-  // cout << "Recebendo frames\n"; ->log
-  frame *f;
+  cout << "Recebendo frames\n";
+  // Fic aouvindo o cliente ate receber um FIMT
   do {
-    if (!receive_valid_frame(&f)) { return; }
-    if (!f) { return; }
-    int frameType = f->get_tipo();
-
-    switch (frameType) {
-    case TEXTO:
-      receive_text(f);
-      continueTransmission = 0;
-      break;
-
-    case MIDIA:
-      receive_midia(f);
-      continueTransmission = 0;
-      break;
-
-    default:
-      break;
+    queue<frame *> frames = receive_frames_window(lastSeq);
+    if ( frames.empty() ) { return; }
+
+    cout << "Quantidade de frames na janela: " << frames.size() << "\n";
+
+    // Ve o que faz com cada frame de acordo com o tipo
+    while ( !frames.empty() )
+    {
+      frame *f = frames.front();
+      frames.pop();
+
+      // Recebeu um frame com erro, retorna um nack e sai da funcao
+      if ( !f->chk_crc8() ) {
+        client_answer.push(create_ack_nack(NACK, f->get_seq()));
+        continue;
+      }
+
+      else { 
+        client_answer.push(create_ack_nack(ACK, f->get_seq()));
+      }
+      
+      cout << "Frame recebido: \n";
+      f->imprime(HEX);
+      cout << "\n";
+
+      int tipo = f->get_tipo();
+      int tam = f->get_tam();
+      char *data_f = f->get_dado();
+
+      switch (tipo)
+      {
+        case FIMT:
+          cout << "Encerrou a transmissao\n";
+          continueTransmission = 0;
+          break;
+
+        case TEXTO:
+          data.insert(data.end(), data_f, data_f + tam);
+          lastSeq = f->get_seq();
+          tipo_data = TEXTO;
+          break;
+
+        case MIDIA:
+          if ( !receive_midia(f) ) { return; }
+          lastSeq = f->get_seq();
+          tipo_data = next_tipo_midia(f);
+          break;
+
+        case DADOS:
+          if ( !receive_midia(f)) { return; }
+          lastSeq = f->get_seq();
+          tipo_data = DADOS;
+          break;
+
+        default:
+          break;
+      }
     }
 
+    cout << "Recebeu todos os frames de uma janela\n";
+
+    // Envia a reposta ao cliente
+    cout << "Enviando acks e nacks para o cliente\n";
+    while ( !client_answer.empty() )
+    {
+      frame *f_answer = client_answer.front();
+      client_answer.pop();
+
+      if (socket->send_frame(f_answer) == -1 )
+      {
+        cout << "Falha ao enviar a resposta\n";
+        return;
+      }
+
+      if (f_answer->get_tipo() == NACK)
+        cout << "NACK " << (int)f_answer->get_dado()[0] << " enviado\n";
+
+      else
+        cout << "ACK " << (int)f_answer->get_dado()[0] << " enviado\n";
+    }
+
+    cout << "Todos os ACKs e NACKs foram enviados\n";
+
   } while (continueTransmission);
+
+  if ( tipo_data == TEXTO )
+    cout << BOLDYELLOW << "\t--Mensagem recebida--\n " << BOLDWHITE
+         << string(data.begin(), data.end()) << "\n"
+         << RESET;
+
+  if ( tipo_data == DADOS )
+    cout << BOLDGREEN << "\t--Arquivo recebido com sucesso--\n" << RESET;
 }
 
 // ------------------------------- PUBLIC --------------------------------- //
@@ -445,7 +595,7 @@ void server::run() {
       continue;
     }
 
-    send_ack(fReceive);
+    if ( send_ack(fReceive) == -1 ) { continue; }
     start_receveing_message();
   }
 }
diff --git a/received/135828 b/received/135828
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/received/foto.jpg b/received/foto.jpg
index 42cedf4a23e28ccea764d16047faa18f7149ddb8..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
Binary files a/received/foto.jpg and b/received/foto.jpg differ
diff --git a/received/texto.txt b/received/texto.txt
index 16914e72e0641b9e2ae68d9c8aef608f1fed464f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/received/texto.txt
+++ b/received/texto.txt
@@ -1,35 +0,0 @@
-  //string fileSize = calc_file_size(fileName);
-  //if (fileSize.empty()) { return; }
-  //franesFile.insert(framesFile.end(), fileSize.begin(), fileSize.end());
-
-  //cout << "Tamanho do arquivo: " << fileSize << "\n";
-  //cout << "Enviando tamanho do arquivo\n";
-  //if (!send_message(vector<char>(fileSize.begin(), fileSize.end()), MIDIA)) {
-  //  cout << "Limite de timout, arquivo nao foi enviado\n";
-  //  return;
-  //}
-
-  // Envia o segundo frame com o nome do arquivo
-  //cout << "Enviando nome do arquivo\n";
-  //string name = "NAME";
-  //vector<char> fileNameVector(name.begin(), name.end());
-  //fileNameVector.insert(fileNameVector.end(), fileName.begin(), fileName.end());
-
-  //if (!send_message(fileNameVector, MIDIA)) {
-  // cout << "Limite de timout, arquivo nao foi enviado\n";
-  //  return;
-  //}
-
-  //cout << "Enviando arquivo\n";
-  //vector<char> file = read_file(fileName);
-  //if ( file.empty())
-  //{
-  //  cout << "Falha ao abrir o arquivo para leitura\n";
-  //  return;
-  //}
-
-  //if (!send_message(file, DADOS)) {
-  // cout << "Limite de timout, arquivo nao foi enviado\n";
-  // return;
-  //}
-
diff --git a/received/todo.txt b/received/todo.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/text.txt b/text.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/todo.txt b/todo.txt
index 108fd2179e3697be302e7ce014a92334f71f5b9d..72ff90813754027306bdbe261c52b201bbe528ef 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,15 +1,15 @@
 -> Ver se os frames que estao vindo sao arquivos e juntar eles no arquivo
 
+<<<<<<< HEAD
 -> Fazer send_error
 
 -> Arrumar o receive text
 
+=======
+>>>>>>> db29f5efa0a686ffe08f19d3553a889be3c6e4d5
 -> Arrumar a interface
 
--> Merge correcao de erro
-  -> Enviar arquivo correcao de erros
-  -> Readme
-  -> Demonstracao
+-> Demonstracao correcao de erros
 
 -> Janela deslizante
   -> Demonstracao