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;
}