diff --git a/src/sender.c b/src/sender.c
index 9fe8f3692788c8612d4c4080ad87053d185b2c4e..4b81e0a5a21becac84af61a118334c20ace08322 100644
--- a/src/sender.c
+++ b/src/sender.c
@@ -118,7 +118,7 @@ int main(int argc, char **argv) {
 
     struct timeval closing_pkt_sent_time;
     struct timeval curr_time;
-    while (state->last_pkt_sent != CLOSING_PKT || state->s_window_size != MAX_WINDOW_SIZE)
+    while ((state->last_pkt_sent != CLOSING_PKT && state->last_pkt_sent != LAST_FEC) || state->s_window_size != MAX_WINDOW_SIZE)
     {
         // Blocking system call
         int rvalue = poll(pfd, 1, -1); // -1 means that there are no setted time out
@@ -134,7 +134,7 @@ int main(int argc, char **argv) {
 
         // Setting a timer only when waiting for the very last ACK
         gettimeofday(&curr_time, NULL);
-        if (state->last_pkt_sent == CLOSING_PKT && ((curr_time.tv_sec - closing_pkt_sent_time.tv_sec) > SENDER_INACTIVE_TIMEOUT))
+        if (state->last_pkt_sent == LAST_FEC && ((curr_time.tv_sec - closing_pkt_sent_time.tv_sec) > SENDER_INACTIVE_TIMEOUT))
         {
             DEBUG("The sender hasn't received any news from the receiver for too long so it TIMEOUT");
             break;
@@ -160,18 +160,26 @@ int main(int argc, char **argv) {
             rvalue = read_and_send(state, sending_fd, socket_fd);
             if (rvalue == -1)
             {
-                free(pfd);
-                state_del(state);
-                close(socket_fd);
-                close(sending_fd);
-                ERROR("read_and_send function failed");
-                return EXIT_FAILURE;
+                if (state->last_pkt_sent == LAST_FEC)
+                {
+                    DEBUG("The very last PTYPE_FEC could not be send because the receiver probably disconnected");
+                    break;
+                }
+                else
+                {
+                    free(pfd);
+                    state_del(state);
+                    close(socket_fd);
+                    close(sending_fd);
+                    ERROR("read_and_send function failed");
+                    return EXIT_FAILURE;
+                }
             }
             // Let's start the timer for the last pkt sent
-            if (state->last_pkt_sent == CLOSING_PKT)
+            if (state->last_pkt_sent == LAST_FEC)
             {
                 gettimeofday(&closing_pkt_sent_time, NULL);
-                DEBUG("A timer of -> %ds <- has started after sending the closing pkt for the first time !", SENDER_INACTIVE_TIMEOUT);
+                DEBUG("A timer of -> %ds <- has started after sending the last FEC pkt !", SENDER_INACTIVE_TIMEOUT);
             }
         }
         else if (pfd->revents & POLLOUT)
@@ -179,9 +187,9 @@ int main(int argc, char **argv) {
             rvalue = checking_timer(state, socket_fd);
             if (rvalue == -1)
             {
-                // If an error occured when trying to send back the CLOSING_PKT,
+                // If an error occured when trying to send back the CLOSING_PKT (so when the last FEC has been sent),
                 // we guess that the receiver has simply disconnected and the ACK of the CLOSING_PKT was lost.
-                if (state->last_pkt_sent == CLOSING_PKT)
+                if (state->last_pkt_sent == LAST_FEC)
                 {
                     DEBUG("The sender can't send anything to the receiver anymore (which has probably disconnected) so it'll disconnect !");
                     break;
diff --git a/src/sender_utils.c b/src/sender_utils.c
index b70b96b5c9c20d74874c69f39e99978bc04338e0..bdcdea1edb7aaeaf009d39ab96ca7b4525fa61b1 100644
--- a/src/sender_utils.c
+++ b/src/sender_utils.c
@@ -21,7 +21,9 @@ sender_state_t *state_new()
     {
         state->map_seqnum_to_buffer_place[i] = OUT_OFF_WINDOW;
     }
-    state->last_pkt_sent = RANDOM_DATA_PKT; // default
+    state->last_pkt_sent = RANDOM_PKT; // default
+    state->FEC = pkt_new();
+    state->FEC_nbr = 0;
     return state;
 }
 
@@ -35,12 +37,13 @@ void state_del(sender_state_t *state)
             pkt_del(state->buffer[i]);
         }
     }
+    pkt_del(state->FEC);
     free(state);
 }
 
 bool can_send(sender_state_t *state)
 {
-    if (state->last_pkt_sent == RANDOM_DATA_PKT)
+    if (state->last_pkt_sent == RANDOM_PKT)
     {
         return (state->r_window_size > 0) && (state->s_window_size > 0);
     }
@@ -50,6 +53,11 @@ bool can_send(sender_state_t *state)
         // it was the end of the file (so that I can set a timer for timeout)
         return state->s_window_size == MAX_WINDOW_SIZE;
     }
+    else if (state->last_pkt_sent == CLOSING_PKT)
+    {
+        return true;
+    }
+    // Case last FEC has been sended
     else
     {
         return false;
@@ -196,69 +204,134 @@ int checking_timer(sender_state_t *state, int socket_fd)
     return 0;
 }
 
-int read_and_send(sender_state_t *state, int sending_fd, int socket_fd)
+bool is_it_EOF(int sending_fd)
 {
-    state->s_window_size--;
-    state->r_window_size--;
-
     // Checking if we're at the end of the file
     off_t curr_position = lseek(sending_fd, 0, SEEK_CUR);
     off_t end_position  = lseek(sending_fd, 0, SEEK_END);
     // put the reader cursor back
     lseek(sending_fd, curr_position, SEEK_SET);
+    return (bool) (curr_position == end_position);
+}
+
+void construct_FEC(sender_state_t *state, pkt_t *pkt)
+{
+    if (state->FEC_nbr == 0)
+    {
+        pkt_set_seqnum(state->FEC, pkt_get_seqnum(pkt));
+    }
 
-    pkt_t *pkt = pkt_new(); 
-    ssize_t nbr_byte_read;
+    uint16_t length = pkt_get_length(state->FEC) ^ pkt_get_length(pkt);
+    pkt_set_length(state->FEC, length);
 
-    // The file has already been read but we need to send an empty DATA
-    if (curr_position == end_position) 
+    uint8_t payload[MAX_PAYLOAD_SIZE];
+    uint8_t *p1 = (uint8_t *) pkt_get_payload(state->FEC);
+    uint8_t *p2 = (uint8_t *) pkt_get_payload(pkt);
+    for (int i = 0; i < MAX_PAYLOAD_SIZE; i++)
     {
-        nbr_byte_read = 0;
-        state->last_pkt_sent = CLOSING_PKT;
-        DEBUG("The CLOSING pkt has been sent !");
+        payload[i] = p1[i] ^ p2[i];
+    }
+    pkt_set_payload(state->FEC, (const char *) payload, MAX_PAYLOAD_SIZE);
+
+    state->FEC_nbr++;
+}
+
+int send_FEC(sender_state_t *state, int socket_fd)
+{
+    if (state->last_pkt_sent == CLOSING_PKT)
+    {
+        state->last_pkt_sent = LAST_FEC;
+        DEBUG("Sending LAST FEC pkt with seqnum: %d", pkt_get_seqnum(state->FEC));
     }
     else 
     {
-        nbr_byte_read = read(sending_fd, pkt->payload, MAX_PAYLOAD_SIZE);
+        DEBUG("Sending FEC pkt with seqnum: %d", pkt_get_seqnum(state->FEC));
     }
+    
+    char packet_to_be_sent[PKT_MAX_LEN];
+    size_t len = PKT_MAX_LEN;
+    pkt_status_code pkt_status = pkt_encode(state->FEC, packet_to_be_sent, &len);
+    if (pkt_status != PKT_OK) 
+    {
+        ERROR("pkt_encode failed with status: %d", pkt_status);
+        return -1;
+    }
+    
+    ssize_t sent = send(socket_fd, packet_to_be_sent, len, 0);
+    if (sent == -1) 
+    {
+        ERROR("The sending (using the function send from <sys/socket.h>) of the pkt failed");
+        return -1;
+    }
+    memset(state->FEC, 0, sizeof(pkt_t));
+    state->FEC_nbr = 0;
+    return 0;
+}
 
-    pkt_set_type(pkt, PTYPE_DATA);
-    pkt_set_tr(pkt, 0);
-    pkt_set_window(pkt, state->s_window_size);
-    pkt_set_length(pkt, nbr_byte_read);
-    pkt_set_seqnum(pkt, state->next_seqnum);
-    // Sending a specific timestamp to let the receiver knows, it is the second to last pkt
-    curr_position = lseek(sending_fd, 0, SEEK_CUR);
-    if (state->last_pkt_sent == RANDOM_DATA_PKT && curr_position == end_position)
+int read_and_send(sender_state_t *state, int sending_fd, int socket_fd)
+{
+    // Checking whether I need to send a PTYPE_FEC or PTYPE_DATA
+    if (state->FEC_nbr == 4 || state->last_pkt_sent == CLOSING_PKT)
     {
-        pkt_set_timestamp(pkt, SECOND_TO_LAST_PKT);
-        state->last_pkt_sent = LAST_DATA_PKT;
-        DEBUG("The LAST DATATYPE is being sent !");
+        return send_FEC(state, socket_fd);
     }
     else
     {
-        pkt_set_timestamp(pkt, 0);
-    }
-    // put the reader cursor back
-    lseek(sending_fd, curr_position, SEEK_SET);
-    
-    // We set the TR to 0 in order to calculcate the CRC on the header
-    char modified_header[8];
-    memcpy((void *) &modified_header, (void *) &pkt->header, 8);
-    modified_header[0] = modified_header[0] & TR_SETTER_TO_ZERO;
-    uint32_t crc1 = htonl(calculate_crc(modified_header, 8));
-    pkt_set_crc1(pkt, crc1);
+        state->s_window_size--;
+        state->r_window_size--;
+
+        pkt_t *pkt = pkt_new(); 
+        ssize_t nbr_byte_read;
+        bool is_EOF = is_it_EOF(sending_fd);
+
+        // The file has already been read but we need to send an empty DATA pkt with length = 0
+        if (is_EOF) 
+        {
+            nbr_byte_read = 0;
+            state->last_pkt_sent = CLOSING_PKT;
+            DEBUG("The CLOSING pkt is being sent !");
+        }
+        else 
+        {
+            nbr_byte_read = read(sending_fd, pkt->payload, MAX_PAYLOAD_SIZE);
+        }
 
-    uint32_t crc2 = htonl(calculate_crc((char *) pkt->payload, (uint32_t) pkt_get_length(pkt)));
-    pkt_set_crc2(pkt, crc2);
+        pkt_set_type(pkt, PTYPE_DATA);
+        pkt_set_tr(pkt, 0);
+        pkt_set_window(pkt, state->s_window_size);
+        pkt_set_length(pkt, nbr_byte_read);
+        pkt_set_seqnum(pkt, state->next_seqnum);
+        // Sending a specific timestamp to let the receiver knows, it is the second to last pkt
+        is_EOF = is_it_EOF(sending_fd);
+        if (state->last_pkt_sent == RANDOM_PKT && is_EOF)
+        {
+            pkt_set_timestamp(pkt, SECOND_TO_LAST_PKT);
+            state->last_pkt_sent = LAST_DATA_PKT;
+            DEBUG("The LAST DATATYPE is being sent !");
+        }
+        else
+        {
+            pkt_set_timestamp(pkt, 0);
+        }
+        
+        // We set the TR to 0 in order to calculcate the CRC on the header
+        char modified_header[8];
+        memcpy((void *) &modified_header, (void *) &pkt->header, 8);
+        modified_header[0] = modified_header[0] & TR_SETTER_TO_ZERO;
+        uint32_t crc1 = htonl(calculate_crc(modified_header, 8));
+        pkt_set_crc1(pkt, crc1);
 
-    if (send_pkt(state, pkt, state->head, socket_fd) == -1) return -1;
+        uint32_t crc2 = htonl(calculate_crc((char *) pkt->payload, (uint32_t) pkt_get_length(pkt)));
+        pkt_set_crc2(pkt, crc2);
 
-    state->map_seqnum_to_buffer_place[pkt_get_seqnum(pkt)] = state->head;
-    state->head = (state->head + 1) % WINDOW_SIZE;
+        if (send_pkt(state, pkt, state->head, socket_fd) == -1) return -1;
+        construct_FEC(state, pkt);
 
-    // Careful we need to convert to uint16_t to avoid overflow
-    state->next_seqnum = (uint8_t) (((uint16_t) state->next_seqnum) + 1) % SEQNUM_RANGE;
+        state->map_seqnum_to_buffer_place[pkt_get_seqnum(pkt)] = state->head;
+        state->head = (state->head + 1) % WINDOW_SIZE;
 
-    return 0;
+        // Careful we need to convert to uint16_t to avoid overflow
+        state->next_seqnum = (uint8_t) (((uint16_t) state->next_seqnum) + 1) % SEQNUM_RANGE;
+        return 0;
+    }
 }
\ No newline at end of file
diff --git a/src/sender_utils.h b/src/sender_utils.h
index c6eb106e9197e1f4d5ed78279f9436a67fce29da..17b11f80b1bfb1f937dc6e276a5cb576849d06cb 100644
--- a/src/sender_utils.h
+++ b/src/sender_utils.h
@@ -24,9 +24,10 @@
 #define OUT_OFF_WINDOW          255
 
 // It is used to identify what kind of pkt was sent lately
-#define RANDOM_DATA_PKT 0
+#define RANDOM_PKT      0
 #define LAST_DATA_PKT   1
 #define CLOSING_PKT     2
+#define LAST_FEC        3
 
 
 /** 
@@ -41,7 +42,9 @@ typedef struct state {
     uint8_t tail;  // place oldest element insert in the buffer                | the start and end of the sender window (of the sended pkt)
     uint8_t next_seqnum;
     uint8_t map_seqnum_to_buffer_place[SEQNUM_RANGE]; // Default value is: OUT_OFF_WINDOW
-    uint8_t last_pkt_sent;  // Can either be: RANDOM_DATA_PKT, LAST_DATA_PKT or CLOSING_PKT
+    uint8_t last_pkt_sent;  // Can either be: RANDOM_PKT, LAST_DATA_PKT, CLOSING_PKT or LAST_FEC
+    pkt_t *FEC;      // The pkt FEC in construction
+    uint8_t FEC_nbr; // The number of PTYPE_DATA stacked on the FEC
 } sender_state_t;
 
 
@@ -101,6 +104,32 @@ int handle_returning_ack_nack(sender_state_t *state, int socket_fd);
  */
 int checking_timer(sender_state_t *state, int socket_fd);
 
+/**
+ * @brief 
+ * 
+ * @param sending_fd 
+ * @return true 
+ * @return false 
+ */
+bool is_it_EOF(int sending_fd);
+
+/**
+ * @brief 
+ * 
+ * @param state 
+ * @param pkt 
+ */
+void construct_FEC(sender_state_t *state, pkt_t *pkt);
+
+/**
+ * @brief 
+ * 
+ * @param state 
+ * @param socket_fd 
+ * @return int 
+ */
+int send_FEC(sender_state_t *state, int socket_fd);
+
 /**
  * @brief When this function is called, the sender MUST be allowed to send a data pkt.
  *        It sends the next pkt and update the variable 'last_pkt_sent' of state.