Este es el código de un emisor en Go-Back-N normal:
timeout = -1; win_size = 0; ExpectedAck = 0; SeqN = 0; for(;;) { switch(Get_next_event(timeout)) { case D_READY: size = FromUpperLayer(buf); <<Armo el paquete Data Link, con checksum y Header (incluye SeqN)>> <<Pongo el paquete en window[Last], con la hora actual>> Fwrite(window[Last].buf, window[Last].size); SeqN++; Last++; win_size++; if( win_size == WINDOW_SIZE ) DisableUpperLayer(); break; case F_TIMEOUT: for(i = First; i < Last; i++) { <<Pongo hora actual en el paquete>> Fwrite(window[i].buf, window[i].size); } break; case F_READY: Fread(Ackbuf, ACK_SIZE); if( Ackbuf[SEQN] == ExpectedAck ) { win_size--; First++; ExpectedAck++; EnableUpperLayer(); } break; } if( win_size > 0 ) timeout = window[First].time + TIMEOUT; else timeout = -1; }
Adapte el código para que implemente timeouts adaptivos a la TCP, estimando RTT y desviación, con el algoritmo de Karn y con aumento exponencial del timeout. Supongo un timeout máximo de TIMEOUT ahora y un valor inicial de 3000 milisegundos.
/* Nuevo */ Timeout = 3000; Rtt = 2000; Mdev = 1000; timeout = -1; win_size = 0; ExpectedAck = 0; SeqN = 0; for(;;) { switch(Get_next_event(timeout)) { case D_READY: size = FromUpperLayer(buf); <<Armo el paquete Data Link, con checksum y Header (incluye SeqN)>> <<Pongo el paquete en window[Last], con la hora actual>> window[Last].retransmit = FALSE; /* Nuevo */ Fwrite(window[Last].buf, window[Last].size); SeqN++; Last++; win_size++; if( win_size == WINDOW_SIZE ) DisableUpperLayer(); break; case F_TIMEOUT: for(i = First; i < Last; i++) { <<Pongo hora actual en el paquete>> window[i].retransmit = TRUE; /* Nuevo */ Fwrite(window[i].buf, window[i].size); } /* Nuevo */ Timeout = Timeout * 2; if(Timeout > TIMEOUT) Timeout = TIMEOUT; break; case F_READY: Fread(Ackbuf, ACK_SIZE); if( Ackbuf[SEQN] == ExpectedAck ) { /* Nuevo */ if(!window[First].retransmit) { Rtt_sample = Time() - window[First].time; Diff = Rtt_sample - Rtt; Rtt = Rtt + alpha * Diff; Mdev = Mdev + alpha * (abs(Diff) - Mdev); Timeout = Rtt + Mdev; } win_size--; First++; ExpectedAck++; EnableUpperLayer(); } break; } if( win_size > 0 ) timeout = window[First].time + Timeout; else timeout = -1; }