Enreas
Advertisement

Código tomado de la página de la cuarta edición del libro "Redes de computadoras", de Andrew S. Tanenbaum: http://authors.phptr.com/tanenbaumcn4/ En concreto, el enlace es: http://authors.phptr.com/tanenbaumcn4/programs/code.zip Por eso los comentarios del código están en inglés.

Declaraciones comunes[]

#define MAX_PKT 1024	/* determines packet size in bytes */

typedef enum {false, true} boolean;	/* boolean type */
typedef unsigned int seq_nr;	/* sequence or ack numbers */
typedef struct {unsigned char data[MAX_PKT];} packet;	/*    packet definition */
typedef enum {data, ack, nak} frame_kind;	/* frame_kind definition */

typedef struct {	/* frames are transported in this layer */
  frame_kind kind;	/* what kind of a frame is it? */
  seq_nr seq;   	/* sequence number */
  seq_nr ack;   	/* acknowledgement number */
  packet info;  	/* the network layer packet */
} frame;

/* Wait for an event to happen; return its type in event. */
void wait_for_event(event_type *event);

/* Fetch a packet from the network layer for transmission on the channel. */
void from_network_layer(packet *p);

/* Deliver information from an inbound frame to the network layer. */
void to_network_layer(packet *p);

/* Go get an inbound frame from the physical layer and copy it to r. */
void from_physical_layer(frame *r);

/* Pass the frame to the physical layer for transmission. */
void to_physical_layer(frame *s);

/* Start the clock running and enable the timeout event. */
void start_timer(seq_nr k);

/* Stop the clock and disable the timeout event. */
void stop_timer(seq_nr k);

/* Start an auxiliary timer and enable the ack_timeout event. */
void start_ack_timer(void);

/* Stop the auxiliary timer and disable the ack_timeout event. */
void stop_ack_timer(void);

/* Allow the network layer to cause a network_layer_ready event. */
void enable_network_layer(void);

/* Forbid the network layer from causing a network_layer_ready event. */
void disable_network_layer(void);

/* Macro inc is expanded in-line: Increment k circularly. */
#define inc(k) if (k < MAX_SEQ) k = k + 1; else k = 0

Un protocolo de ventana corrediza de un bit[]

/* Protocol 4 (sliding window) is bidirectional. */
#define MAX_SEQ 1		/* must be 1 for protocol 4 */
typedef enum {frame_arrival, cksum_err, timeout} event_type;
#include "protocol.h"
void protocol4 (void)
{
  seq_nr next_frame_to_send;	/* 0 or 1 only */
  seq_nr frame_expected;	/* 0 or 1 only */
  frame r, s;			/* scratch variables */
  packet buffer;		/* current packet being sent */
  event_type event;
  next_frame_to_send = 0;	/* next frame on the outbound stream */
  frame_expected = 0;		/* frame expected next */
  from_network_layer(&buffer);	/* fetch a packet from the network layer */
  s.info = buffer;		/* prepare to send the initial frame */
  s.seq = next_frame_to_send;	/* insert sequence number into frame */
  s.ack = 1 - frame_expected;	/* piggybacked ack */
  to_physical_layer(&s);	/* transmit the frame */
  start_timer(s.seq);		/* start the timer running */
  while (true) {
        wait_for_event(&event);	/* frame_arrival, cksum_err, or timeout */
        if (event == frame_arrival) {		    /* a frame has arrived undamaged. */
                from_physical_layer(&r);	    /* go get it */
                if (r.seq == frame_expected) {	    /* handle inbound frame stream. */
                        to_network_layer(&r.info);  /* pass packet to network layer */
                        inc(frame_expected);	    /* invert seq number expected next */
                }
                if (r.ack == next_frame_to_send) {  /* handle outbound frame stream. */
                        stop_timer(r.ack);	    /* turn the timer off */
                        from_network_layer(&buffer);/* fetch new pkt from network layer */
                        inc(next_frame_to_send);    /* invert sender's sequence number */
                }
        }
        s.info = buffer;		/* construct outbound frame */
        s.seq = next_frame_to_send;	/* insert sequence number into it */
        s.ack = 1 - frame_expected;	/* seq number of last received frame */
        to_physical_layer(&s);		/* transmit a frame */
        start_timer(s.seq);		/* start the timer running */
  }
}

Protocolo que usa retroceso N[]

/* Protocol 5 (go back n) allows multiple outstanding frames. The sender may transmit up
   to MAX_SEQ frames without waiting for an ack. In addition, unlike in the previous
   protocols, the network layer is not assumed to have a new packet all the time. Instead,
   the network layer causes a network_layer_ready event when there is a packet to send. */

#define MAX_SEQ 7		/* should be 2^n - 1 */
typedef enum {frame_arrival, cksum_err, timeout, network_layer_ready} event_type;
#include "protocol.h"

static boolean between(seq_nr a, seq_nr b, seq_nr c)
{
/* Return true if a <=b < c circularly; false otherwise. */
  if (((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a)))
        return(true);
    else
        return(false);
}

static void send_data(seq_nr frame_nr, seq_nr frame_expected, packet buffer[])
{
/* Construct and send a data frame. */
  frame s;			/* scratch variable */

  s.info = buffer[frame_nr];	/* insert packet into frame */
  s.seq = frame_nr;		/* insert sequence number into frame */
  s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1);	/* piggyback ack */
  to_physical_layer(&s);	/* transmit the frame */
  start_timer(frame_nr);	/* start the timer running */
}

void protocol5(void)
{
  seq_nr next_frame_to_send;	/* MAX_SEQ > 1; used for outbound stream */
  seq_nr ack_expected;		/* oldest frame as yet unacknowledged */
  seq_nr frame_expected;	/* next frame expected on inbound stream */
  frame r;			/* scratch variable */
  packet buffer[MAX_SEQ + 1];	/* buffers for the outbound stream */
  seq_nr nbuffered;		/* # output buffers currently in use */
  seq_nr i;			/* used to index into the buffer array */
  event_type event;

  enable_network_layer();	/* allow network_layer_ready events */
  ack_expected = 0;		/* next ack expected inbound */
  next_frame_to_send = 0;	/* next frame going out */
  frame_expected = 0;		/* number of frame expected inbound */
  nbuffered = 0;		/* initially no packets are buffered */
  while (true) {
     wait_for_event(&event);	/* four possibilities: see event_type above */

     switch(event) { 
        case network_layer_ready:		/* the network layer has a packet to send */
                /* Accept, save, and transmit a new frame. */
                from_network_layer(&buffer[next_frame_to_send]); /* fetch new packet */
                nbuffered = nbuffered + 1;	/* expand the sender's window */
                send_data(next_frame_to_send, frame_expected, buffer);	/* transmit the frame */
                inc(next_frame_to_send);	/* advance sender's upper window edge */
                break;
  
        case frame_arrival:			/* a data or control frame has arrived */
                from_physical_layer(&r);	/* get incoming frame from physical layer */
  
                if (r.seq == frame_expected) {
                        /* Frames are accepted only in order. */
                        to_network_layer(&r.info); /* pass packet to network layer */
                        inc(frame_expected);	/* advance lower edge of receiver's window */
                 }
  
                 /* Ack n implies n - 1, n - 2, etc.  Check for this. */
                while (between(ack_expected, r.ack, next_frame_to_send)) {
                        /* Handle piggybacked ack. */
                        nbuffered = nbuffered - 1; /* one frame fewer buffered */
                        stop_timer(ack_expected);  /* frame arrived intact; stop timer */
                        inc(ack_expected);	   /* contract sender's window */
                }
                break;

        case cksum_err: break;			   /* just ignore bad frames */
  
        case timeout:	/* trouble; retransmit all outstanding frames */
                next_frame_to_send = ack_expected; /* start retransmitting here */
                for (i = 1; i <= nbuffered; i++) {
                        send_data(next_frame_to_send, frame_expected, buffer);	/* resend 1 frame */
                        inc(next_frame_to_send);   /* prepare to send the next one */
                }

     }
  
     if (nbuffered < MAX_SEQ)
                enable_network_layer();
     else
                disable_network_layer();
  }
}
Advertisement