⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simulator.c

📁 计算机网络中的几个简单协议的仿真代码
💻 C
📖 第 1 页 / 共 2 页
字号:
  if (frct > 0) {	/* How many frames can be read consecutively? */	top = (outp <= inp ? &queue[MAX_QUEUE] : outp);/* how far can we rd?*/	k = top - inp;	/* number of frames that can be read consecutively */	if (k > frct) k = frct;	/* how many frames to read from peer */	if (read(prfd, inp, k * FRAME_SIZE) != k * FRAME_SIZE)		sim_error("Error reading frames from peer");	frct -= k;		/* residual frames not yet read */	inp += k;	if (inp == &queue[MAX_QUEUE]) inp = queue;	nframes += k;	/* If frct is still > 0, the queue has been filled to the upper	 * limit, but there is still space at the bottom.  Continue reading	 * there.  This mechanism makes queue a circular buffer.	 */	if (frct > 0) {		if (read(prfd, queue, frct * FRAME_SIZE) != frct*FRAME_SIZE)			sim_error("Error 2 reading frames from peer");		nframes += frct;		inp = &queue[frct];	}  }}int pick_event(void){/* Pick a random event that is now possible for the process. * Note that the order in which the tests is made is critical, as it gives * priority to some events over others.  For example, for protocols 3 and 4 * frames will be delivered before a timeout will be caused.  This is probably * a reasonable strategy, and more closely models how a real line works. */  if (check_ack_timer() > 0) return(ack_timeout);  if (nframes > 0) return((int)frametype());  if (network_layer_status) return(network_layer_ready);  if (check_timers() >= 0) return(timeout);	/* timer went off */  return(NO_EVENT);}event_type frametype(void){/* This function is called after it has been decided that a frame_arrival * event will occur.  The earliest frame is removed from queue[] and copied * to last_frame.  This copying is needed to avoid messing up the simulation * in the event that the protocol does not actually read the incoming frame. * For example, in protocols 2 and 3, the senders do not call * from_physical_layer() to collect the incoming frame. If frametype() did * not remove incoming frames from queue[], they never would be removed. * Of course, one could change sender2() and sender3() to have them call * from_physical_layer(), but doing it this way is more robust. * * This function determines (stochastically) whether the arrived frame is good * or bad (contains a checksum error). */  int n, i;  event_type event;  /* Remove one frame from the queue. */  last_frame = *outp;		/* copy the first frame in the queue */  outp++;  if (outp == &queue[MAX_QUEUE]) outp = queue;  nframes--;  /* Generate frames with checksum errors at random. */  n = rand() & 01777;  if (n < garbled) {	/* Checksum error.*/	event = cksum_err;	if (last_frame.kind == data) cksum_data_recd++;	if (last_frame.kind == ack) cksum_acks_recd++;	i = 0;  } else {	event = frame_arrival;	if (last_frame.kind == data) good_data_recd++;	if (last_frame.kind == ack) good_acks_recd++;	i = 1;  }  if (debug_flags & RECEIVES) {	printf("Tick %u. Proc %d got %s frame:  ",						tick/DELTA,id,badgood[i]);	fr(&last_frame);  }  return(event);}void from_network_layer(packet *p){/* Fetch a packet from the network layer for transmission on the channel. */  p->data[0] = (next_net_pkt >> 24) & BYTE;  p->data[1] = (next_net_pkt >> 16) & BYTE;  p->data[2] = (next_net_pkt >>  8) & BYTE;  p->data[3] = (next_net_pkt      ) & BYTE;  next_net_pkt++;}void to_network_layer(packet *p){/* Deliver information from an inbound frame to the network layer. A check is * made to see if the packet is in sequence.  If it is not, the simulation * is terminated with a "protocol error" message. */  unsigned int num;  num = pktnum(p);  if (num != last_pkt_given + 1) {	printf("Tick %u. Proc %d got protocol error.  Packet delivered out of order.\n", tick/DELTA, id); 	printf("Expected payload %d but got payload %d\n",last_pkt_given+1,num);	exit(0);  }  last_pkt_given = num;  payloads_accepted++;}  void from_physical_layer (frame *r){/* Copy the newly-arrived frame to the user. */ *r = last_frame;}void to_physical_layer(frame *s){/* Pass the frame to the physical layer for writing on pipe 1 or 2.  * However, this is where bad packets are discarded: they never get written. */  int fd, got, k;  /* The following statement is essential to later on determine the timed   * out sequence number, e.g. in protocol 6. Keeping track of   * this information is a bit tricky, since the call to start_timer()   * does not tell what the sequence number is, just the buffer.  The   * simulator keeps track of sequence numbers using the array seqs[],   * which records the sequence number of each data frame sent, so on a   * timeout, knowing the buffer number makes it possible to determine   * the sequence number.   */  if (s->kind==data) seqs[s->seq % (nseqs/2)] = s->seq;   if (s->kind == data) data_sent++;  if (s->kind == ack) acks_sent++;  if (retransmitting) data_retransmitted++;  /* Bad transmissions (checksum errors) are simulated here. */  k = rand() & 01777;		/* 0 <= k <= about 1000 (really 1023) */  if (k < pkt_loss) {	/* simulate packet loss */	if (debug_flags & SENDS) {		printf("Tick %u. Proc %d sent frame that got lost: ",							    tick/DELTA, id);		fr(s);	}	if (s->kind == data) data_lost++;	/* statistics gathering */	if (s->kind == ack) acks_lost++;	/* ditto */	return;  }  if (s->kind == data) data_not_lost++;		/* statistics gathering */  if (s->kind == ack) acks_not_lost++;		/* ditto */  fd = (id == 0 ? w1 : w2);  got = write(fd, s, FRAME_SIZE);  if (got != FRAME_SIZE) print_statistics();	/* must be done */  if (debug_flags & SENDS) {	printf("Tick %u. Proc %d sent frame: ", tick/DELTA, id);	fr(s);  }}void start_timer(seq_nr k){/* Start a timer for a data frame. */  ack_timer[k] = tick + timeout_interval + offset;  offset++;  recalc_timers();		/* figure out which timer is now lowest */}void stop_timer(seq_nr k){/* Stop a data frame timer. */  ack_timer[k] = 0;  recalc_timers();		/* figure out which timer is now lowest */}void start_ack_timer(void){/* Start the auxiliary timer for sending separate acks. The length of the * auxiliary timer is arbitrarily set to half the main timer.  This could * have been another simulation parameter, but that is unlikely to have * provided much extra insight. */  aux_timer = tick + timeout_interval/AUX;  offset++;}void stop_ack_timer(void){/* Stop the ack timer. */  aux_timer = 0;}void enable_network_layer(void){/* Allow network_layer_ready events to occur. */  network_layer_status = 1;}void disable_network_layer(void){/* Prevent network_layer_ready events from occuring. */  network_layer_status = 0;}int check_timers(void){/* Check for possible timeout.  If found, reset the timer. */  int i;  /* See if a timeout event is even possible now. */  if (lowest_timer == 0 || tick < lowest_timer) return(-1);  /* A timeout event is possible.  Find the lowest timer. Note that it is   * impossible for two frame timers to have the same value, so that when a   * hit is found, it is the only possibility.  The use of the offset variable   * guarantees that each successive timer set gets a higher value than the   * previous one.   */  for (i = 0; i < NR_TIMERS; i++) {	if (ack_timer[i] == lowest_timer) {		ack_timer[i] = 0;	/* turn the timer off */		recalc_timers();	/* find new lowest timer */                oldest_frame = seqs[i];	/* timed out sequence number */		return(i);	}  }  printf("Impossible.  check_timers failed at %d\n", lowest_timer);  exit(1);}int check_ack_timer(){/* See if the ack timer has expired. */  if (aux_timer > 0 && tick >= aux_timer) {	aux_timer = 0;	return(1);  } else {	return(0);  }}unsigned int pktnum(packet *p){/* Extract packet number from packet. */  unsigned int num, b0, b1, b2, b3;  b0 = p->data[0] & BYTE;  b1 = p->data[1] & BYTE;  b2 = p->data[2] & BYTE;  b3 = p->data[3] & BYTE;  num = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;  return(num);}void fr(frame *f){/* Print frame information for tracing. */  printf("type=%s  seq=%d  ack=%d  payload=%d\n",	tag[f->kind], f->seq, f->ack, pktnum(&f->info));}void recalc_timers(void){/* Find the lowest timer */  int i;  bigint t = UINT_MAX;  for (i = 0; i < NR_TIMERS; i++) {	if (ack_timer[i] > 0 && ack_timer[i] < t) t = ack_timer[i];  }  lowest_timer = t;}void print_statistics(void){/* Display statistics. */  int word[3];  sleep(1);  printf("\nProcess %d:\n", id);  printf("\tTotal data frames sent:  %9d\n", data_sent);  printf("\tData frames lost:        %9d\n", data_lost);  printf("\tData frames not lost:    %9d\n", data_not_lost);  printf("\tFrames retransmitted:    %9d\n", data_retransmitted);  printf("\tGood ack frames rec'd:   %9d\n", good_acks_recd);  printf("\tBad ack frames rec'd:    %9d\n\n", cksum_acks_recd);  printf("\tGood data frames rec'd:  %9d\n", good_data_recd);  printf("\tBad data frames rec'd:   %9d\n", cksum_data_recd);  printf("\tPayloads accepted:       %9d\n", payloads_accepted);  printf("\tTotal ack frames sent:   %9d\n", acks_sent);  printf("\tAck frames lost:         %9d\n", acks_lost);  printf("\tAck frames not lost:     %9d\n", acks_not_lost);  printf("\tTimeouts:                %9d\n", timeouts);  printf("\tAck timeouts:            %9d\n", ack_timeouts);  fflush(stdin);  word[0] = 0;  word[1] = payloads_accepted;  word[2] = data_sent;  write(mwfd, word, 3*sizeof(int));	/* tell main we are done printing */  sleep(1);  exit(0);}void sim_error(char *s){/* A simulator error has occurred. */  int fd;  printf("%s\n", s);  fd = (id == 0 ? w4 : w6);  write(fd, &zero, TICK_SIZE);  exit(1);}int parse_first_five_parameters(int argc, char *argv[], long *event, int *timeout_interval, int *pkt_loss, int *garbled, int *debug_flags){/* Help function for protocol writers to parse first five command-line * parameters that the simulator needs. */  if (argc < 6) {        printf("Need at least five command-line parameters.\n");        return(0);  }  *event = atol(argv[1]);  if (*event < 0) {        printf("Number of simulation events must be positive\n");        return(0);  }  *timeout_interval = atoi(argv[2]);  if (*timeout_interval < 0){        printf("Timeout interval must be positive\n");        return(0);  }  *pkt_loss = atoi(argv[3]);     /* percent of sends that chuck pkt out */  if (*pkt_loss < 0 || *pkt_loss > 99) {        printf("Packet loss rate must be between 0 and 99\n");        return(0);  }  *garbled = atoi(argv[4]);  if (*garbled < 0 || *garbled > 99) {        printf("Packet cksum rate must be between 0 and 99\n");        return(0);  }  *debug_flags = atoi(argv[5]);  if (*debug_flags < 0) {        printf("Debug flags may not be negative\n");        return(0);  }  return(1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -