void sender3(void) { seq_nr next_frame_to_send; /* seq number of next outgoing frame */ frame s; /* scratch variable */ packet buffer; /* buffer for an outbound packet */ event_type event; next_frame_to_send = 0; /* initialize outbound sequence numbers */ from_network_layer(&buffer); /* fetch first packet */ while (true) { init_frame(&s); s.info = buffer; /* construct a frame for transmission */ s.seq = next_frame_to_send; /* insert sequence number in frame */ to_physical_layer(&s); /* send it on its way */ start_timer(s.seq); /* if answer takes too long, time out */ wait_for_event(&event); /* frame_arrival, cksum_err, timeout */ if (event == frame_arrival) { from_physical_layer(&s); /* get the acknowledgement */ if (s.ack == next_frame_to_send) { from_network_layer(&buffer); /* get the next one to send */ inc(next_frame_to_send); /* invert next_frame_to_send */ } } } }
void receiver3(void) { seq_nr frame_expected; frame r, s; event_type event; frame_expected = 0; while (true) { wait_for_event(&event); /* possibilities: frame_arrival, cksum_err */ if (event == frame_arrival) { /* A valid frame has arrived. */ from_physical_layer(&r); /* go get the newly arrived frame */ if (r.seq == frame_expected) { /* This is what we have been waiting for. */ to_network_layer(&r.info); /* pass the data to the network layer */ inc(frame_expected); /* next time expect the other sequence nr */ } init_frame(&s); s.ack = 1 - frame_expected; /* tell which frame is being acked */ to_physical_layer(&s); /* only the ack field is use */ } } }
void protocol6(void) { seq_nr ack_expected; /* lower edge of sender's window */ seq_nr next_frame_to_send; /* upper edge of sender's window + 1 */ seq_nr frame_expected; /* lower edge of receiver's window */ seq_nr too_far; /* upper edge of receiver's window + 1 */ int i; /* index into buffer pool */ frame r; /* scratch variable */ packet out_buf[NR_BUFS]; /* buffers for the outbound stream */ packet in_buf[NR_BUFS]; /* buffers for the inbound stream */ boolean arrived[NR_BUFS]; /* inbound bit map */ seq_nr nbuffered; /* how many output buffers currently used */ event_type event; enable_network_layer(); /* initialize */ ack_expected = 0; /* next ack expected on the inbound stream */ next_frame_to_send = 0; /* number of next outgoing frame */ frame_expected = 0; /* frame number expected */ too_far = NR_BUFS; /* receiver's upper window + 1 */ nbuffered = 0; /* initially no packets are buffered */ for (i = 0; i < NR_BUFS; i++) arrived[i] = false; while (true) { wait_for_event(&event); /* five possibilities: see event_type above */ switch(event) { case network_layer_ready: /* accept, save, and transmit a new frame */ nbuffered = nbuffered + 1; /* expand the window */ from_network_layer(&out_buf[next_frame_to_send % NR_BUFS]); /* fetch new packet */ send_frame(data, next_frame_to_send, frame_expected, out_buf); /* transmit the frame */ inc(next_frame_to_send); /* advance upper window edge */ break; case frame_arrival: /* a data or control frame has arrived */ from_physical_layer(&r); /* fetch incoming frame from physical layer */ if (r.kind == data) { /* An undamaged frame has arrived. */ if ((r.seq != frame_expected) && no_nak) send_frame(nak, 0, frame_expected, out_buf); else start_ack_timer(); if (between(frame_expected, r.seq, too_far) && (arrived[r.seq%NR_BUFS] == false)) { /* Frames may be accepted in any order. */ arrived[r.seq % NR_BUFS] = true; /* mark buffer as full */ in_buf[r.seq % NR_BUFS] = r.info; /* insert data into buffer */ while (arrived[frame_expected % NR_BUFS]) { /* Pass frames and advance window. */ to_network_layer(&in_buf[frame_expected % NR_BUFS]); no_nak = true; arrived[frame_expected % NR_BUFS] = false; inc(frame_expected); /* advance lower edge of receiver's window */ inc(too_far); /* advance upper edge of receiver's window */ start_ack_timer(); /* to see if (a separate ack is needed */ } } } if((r.kind==nak) && between(ack_expected,(r.ack+1)%(MAX_SEQ+1),next_frame_to_send)) send_frame(data, (r.ack+1) % (MAX_SEQ + 1), frame_expected, out_buf); while (between(ack_expected, r.ack, next_frame_to_send)) { nbuffered = nbuffered - 1; /* handle piggybacked ack */ stop_timer(ack_expected % NR_BUFS); /* frame arrived intact */ inc(ack_expected); /* advance lower edge of sender's window */ } break; case cksum_err: if (no_nak) send_frame(nak, 0, frame_expected, out_buf); break; /* damaged frame */ case timeout: send_frame(data, get_timedout_seqnr(), frame_expected, out_buf); break; /* we timed out */ case ack_timeout: send_frame(ack,0,frame_expected, out_buf); /* ack timer expired; send ack */ } if (nbuffered < NR_BUFS) enable_network_layer(); else disable_network_layer(); } }
/*frame *trama_e, int fde,TEntity *active_en, TAutomat *automata */ void recibe_ACK(Argumentos * argu, TAutomat *automata, int fin_f) { int tam_trama,conretx; frame trama_recb; long t_ini,t_actual; char aux; struct timeval tiempo; STOP=FALSE; conretx=0; /* //Empieza el temporizador */ semaphore_timeout_set(argu->tempo,argu,automata); gettimeofday(&tiempo,NULL); t_ini= tiempo.tv_sec+(long)argu->tempo+1; while (STOP==FALSE) { gettimeofday(&tiempo,NULL); /* printf("t_ini = %i\n", t_ini); printf("t actual = %i \n", tiempo.tv_sec); */ if ( (t_ini+(long)argu->tempo) <= tiempo.tv_sec ){ t_ini =tiempo.tv_sec; printf("Reenviamos trama desde temporizador \n"); automat_transit(argu->active_en, automata, TIME_O, argu); argu->tr_perdidas ++; } printf("."); printf("bucle - espero ACK\n"); usleep(100000); /*tras recibir SIGIO, wait_flag = FALSE, la entrada esta disponible y puede ser leida */ // printf("En el recibe_ack el wait_flag vale :%i \n", wait_flag); if (wait_flag==FALSE) { //Al recibir datos en el canal cancelo el temporizador semaphore_timeout_cancel( ); //tam_trama = from_physical_layer(argu->trama_e, argu->fde); //printf("control : %c \n", argu->trama_e->control); //if ( c=='A'/*128 ACK*/){ tam_trama = from_physical_layer(&trama_recb, argu->fde); printf("control : %c \n", trama_recb.control); if ( trama_recb.control=='A'/*128 ACK*/){ //Si el ACK no lleva la secuencia para la siguiente trama if (argu->sec_siguiente != trama_recb.address) { //transito automa con ese evento automat_transit(argu->active_en, automata, ACK_N_SIG, argu); } else //else1-> Si el ACK lleva la secuencia para la siguiente trama { argu->sec_actual= argu->sec_siguiente; //Se desdignan la secuencia actual y la secuencia esperada switch (argu->sec_actual) { case 'A': { printf("Estoy en A espero un B \n" ); argu->sec_siguiente = 'B'; break; } case 'B': { printf("Estoy en B espero un A \n" ); argu->sec_siguiente = 'A'; break; } default : { printf("Es un estado no designado \n"); break; } } /*copiamos los datos de la trama al paquete*/ printf(" Recibimos el ACK \n"); STOP=TRUE; /* para el bucle si solo entra un CR */ printf(" \n Para, y enviamos la siguiente trama \n"); //Para enviar la trama vacia if (fin_f ==0){ /* entidad , automata, evento, argumentos de evento */ automat_transit(argu->active_en, automata, ACK_SIG, argu); } else{ printf(" \n Se ha enviado la ultima trama \n"); argu->trama_e->data[0]='\0'; argu->trama_e->control='T';//0x09; printf("Se envia la trama vacia %s: ,tam : %d \n",argu->trama_e->data,strlen(argu->trama_e->data)); to_physical_layer(argu->trama_e,argu->fde); automat_transit(argu->active_en,automata,ACK_0, argu); } /*Se puede borrar ya que paramos*/ wait_flag = TRUE; /* espera una nueva entrada */ }//else 1 }//if else//else2 { //Si el NACK lleva la secuencia de la trama actual if (argu->sec_actual == trama_recb.address) { /*Como sria un Nack se puede hacer una comprobafcion de la secuencia*/ if (conretx == argu->n_rtx) { automat_transit(argu->active_en, automata, N_NACK_MAX, argu); printf("Se ha superado el numero de retransmisiones por trama \n"); printf("ERROR en el canal \n"); exit(-1); } conretx++; printf("El limite de retrasnmisiones es %i veces\n", argu->n_rtx); printf("Se ha retransmitido %i veces\n", conretx); printf("Recibido Recibo Nack\n"); automat_transit(argu->active_en, automata, NACK_ACT, argu); /* //Empieza otra vez el temporizador por el reenvio temporizador*/ semaphore_timeout_set(argu->tempo,argu,automata); gettimeofday(&tiempo,NULL); t_ini= tiempo.tv_sec+(long)argu->tempo+1; printf("Se ha reenviado la trama\n"); wait_flag = TRUE; /* espera una nueva entrada */ } else //else23-> Si el NACK no lleva la secuencia de la trama actual { //transito automa con ese evento automat_transit(argu->active_en, automata, NACK_N_ACT, argu); } }//else2 }//if }//while }