Advertisement
Guest User

saw_sender.c

a guest
Feb 25th, 2013
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.20 KB | None | 0 0
  1. // Implementation of the Stop-and-Wait Protocol
  2. /**************************SENDER PROGRAM**********************************
  3.  * Author:- Parth Joshi
  4.  * Roll No:- CS09B051
  5.  *
  6.  * USAGE:- ./sender [-s <RECEIVER_URL>] [-p <PORT_NO>] [-l <PACKET_LENGTH>]
  7.                    [-r <PACKET_GEN_RATE>] [-n <MAX_PACKETS>] [-d]
  8.  * The default values of the above parameters are taken to be:-
  9.  * Server address         -- localhost
  10.  * Server port            -- 22051
  11.  * Packet length          -- 512 bytes
  12.  * Packet generation rate -- 10 packets/second
  13.  * Maximum no of packets  -- 400
  14.  * NODEBUG mode
  15. **************************************************************************/
  16.  
  17. #include <sys/types.h>
  18. #include <sys/socket.h>
  19. #include <sys/select.h>
  20. #include <sys/time.h>
  21. #include <netinet/in.h>
  22. #include <arpa/inet.h>  //for inet_ntoa()
  23. #include <netdb.h>      //for struct hostent, gethostbyname()
  24. #include <stdio.h>
  25. #include <unistd.h>
  26. #include <errno.h>
  27. #include <string.h>
  28. #include <math.h>       //for ceil()
  29. #include <stdlib.h>
  30. #include <pthread.h>
  31.  
  32. #define TO_SEC  0
  33. #define TO_USEC 100*1000 //timeout limit in ms
  34.  
  35. #define DEF_RECV_ADDR       "localhost"
  36. #define DEF_RECV_PORT       22051
  37. #define DEF_PKT_LEN         512
  38. #define DEF_PKT_GEN_RATE    10
  39. #define DEF_MAX_PKTS        400
  40. #define DEF_ACK_PKT_LEN     60
  41. #define DEF_SEQ_BITS        8
  42.  
  43. /* error handling macros */
  44.  
  45. // handling thread errors (which do not set errno)
  46. #define handle_error_th(err, msg) \
  47.     do { errno = err; perror(msg); exit(EXIT_FAILURE); } while(0)
  48.  
  49. //handling other system call errors (which set errno)
  50. #define handle_error(msg) \
  51.     do { perror(msg); exit(EXIT_FAILURE); } while(0)
  52.  
  53.  
  54.  
  55. char **buffer = NULL;  /* the sender buffer used to store packets as they
  56.                           are generated */
  57. // char **front = NULL, **back = NULL /* pointers to mark the beginning
  58. //                                      and end of the queue */
  59.  
  60. typedef struct packet_generator_args
  61. {
  62.     int max_pkts;
  63.     int pkt_len;
  64.     int pkt_gen_rate;
  65. } pktgen_args;
  66.  
  67. /*void push_into_buffer(packet_t *pkt)
  68. {
  69. }
  70.  
  71. packet_t pop_from_buffer()
  72. {
  73. }*/
  74.  
  75. /* uniform distribution on (0..1] */
  76. double drand()
  77. {
  78.     return (rand()+1.0)/(RAND_MAX+1.0);
  79. }
  80.  
  81. /* normal distribution, centered on 0, std dev 1 using Box-Muller transform */
  82. double random_normal()
  83. {
  84.     return sqrt(-2*log(drand())) * cos(2*M_PI*drand());
  85. }
  86.  
  87. /* returns a random wait time sampled from a normal distribution with
  88.    mean time determined according to the parameter pkt_gen_rate and
  89.    std dev calculated as 5% of the mean value */
  90. void random_wait(int pkt_gen_rate, struct timeval *rwait)
  91. {
  92.     struct timeval dev, mean;
  93.     mean.tv_sec = dev.tv_sec = 0;
  94.     mean.tv_usec = 1000000/pkt_gen_rate;
  95.     dev.tv_usec = (suseconds_t)(0.05 * mean.tv_usec * random_normal());
  96.     timeradd(&mean, &dev, rwait);
  97. }
  98.  
  99. /* generates and buffers packets at a mean rate given by the
  100.    pkt_gen_rate field of its argument; runs in a separate thread  */
  101. void *generate_packets(void *arg)
  102. {
  103.     pktgen_args *opts = (pktgen_args *)arg; // error occurs after execution of this line
  104.     buffer = (char **)calloc((size_t)opts->max_pkts, sizeof(char *));
  105.     if (buffer == NULL)
  106.         handle_error("Calloc Error");
  107.     //front = back = buffer;
  108.  
  109.     int i;
  110.     struct timeval gen_time, wait_time;
  111.     //packet_t *new;
  112.  
  113.     srand(time(NULL));
  114.     for (i=0; i<opts->max_pkts; i++)
  115.     {
  116.         if ((buffer[i] = calloc((size_t)opts->pkt_len, sizeof(char))) == NULL)
  117.             handle_error("Calloc Error");
  118.         buffer[i][0] = i%(1<<DEF_SEQ_BITS);
  119.         gettimeofday(&gen_time, NULL);
  120.         memcpy((void *)(buffer[i]+1), &gen_time, sizeof(struct timeval));
  121.         random_wait(opts->pkt_gen_rate, &wait_time);
  122.         if (select(0, NULL, NULL, NULL, &wait_time) == -1)
  123.             handle_error("Wait Error");
  124.     }
  125.     return 0;
  126. }
  127.  
  128. int main(int argc,char *argv[])
  129. {
  130.     pktgen_args thread_args;
  131.     thread_args.pkt_len = DEF_PKT_LEN;
  132.     thread_args.pkt_gen_rate = DEF_PKT_GEN_RATE;
  133.     thread_args.max_pkts = DEF_MAX_PKTS;
  134.     short server_port = DEF_RECV_PORT;
  135.     char serv_host_name[30] = DEF_RECV_ADDR;
  136.     char debug_mode = 0;
  137.     int tx_attempts, pkts_ackd, total_transmissions;
  138.     double tx_efficiency, throughput;
  139.  
  140.     int sock, addr_len;
  141.     struct sockaddr_in server_addr;
  142.     struct hostent *host;
  143.     unsigned char *send_data, recv_data[DEF_ACK_PKT_LEN];
  144.     const char USAGE_STR[] = "USAGE: ./sender [-s <RECEIVER_URL>] [-p <PORT_NO>] [-l <PACKET_LENGTH>] [-r <PACKET_GEN_RATE>] [-n <MAX_PACKETS>] [-d]\n";
  145.     int retval, bytes_read, i;
  146.     fd_set rfds;
  147.     struct timeval prog_start, prog_end, exec_time;
  148.     struct timeval gen_time, ack_time, timeout;
  149.  
  150.     //command line options
  151.     for (i=1; i<10; i+=2)
  152.     {
  153.         if (argc <= i+1)
  154.             break;
  155.        
  156.         if (strcmp(argv[i], "-p") == 0)
  157.             server_port = atoi(argv[i+1]);
  158.         else if (strcmp(argv[i], "-s") == 0)
  159.             strcpy(serv_host_name, argv[i+1]);
  160.         else if (strcmp(argv[i], "-l") == 0)
  161.             thread_args.pkt_len = atoi(argv[i+1]);
  162.         else if (strcmp(argv[i], "-r") == 0)
  163.             thread_args.pkt_gen_rate = atoi(argv[i+1]);
  164.         else if (strcmp(argv[i], "-n") == 0)
  165.             thread_args.max_pkts = atoi(argv[i+1]);
  166.         else
  167.         {
  168.             printf("%s", USAGE_STR);
  169.             exit(EXIT_FAILURE);
  170.         }
  171.     }
  172.     if (argc == i+1)
  173.     {
  174.         if (strcmp(argv[i], "-d") == 0)
  175.             debug_mode = 1;
  176.         else
  177.         {
  178.             printf("%s", USAGE_STR);
  179.             exit(EXIT_FAILURE);
  180.         }
  181.     }
  182.  
  183.     gettimeofday(&prog_start, NULL);
  184.    
  185.     host = (struct hostent *) gethostbyname(serv_host_name);
  186.  
  187.     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
  188.         handle_error("Socket Error");
  189.  
  190.     server_addr.sin_family = AF_INET;
  191.     server_addr.sin_port = htons(server_port);
  192.     server_addr.sin_addr = *((struct in_addr *)host->h_addr);
  193.     memset(&(server_addr.sin_zero),0,8);
  194.  
  195.     //generate data packets at the rate of thread_args.pkt_gen_rate
  196.     pthread_t packet_generator;
  197.     pktgen_args *thread_args1 = (pktgen_args *)malloc(sizeof(pktgen_args));
  198.     memcpy((void *)thread_args1, (void *)&thread_args, sizeof(pktgen_args));
  199.     retval = pthread_create(&packet_generator, NULL, &generate_packets, (void *)thread_args1);
  200.     if (retval != 0)
  201.         handle_error_th(retval, "Thread Creation Error");
  202.  
  203.     for (pkts_ackd = 0, total_transmissions = 0; pkts_ackd < thread_args.max_pkts; pkts_ackd++)
  204.     {
  205.         while (!buffer[pkts_ackd]); /* wait as long as the next pkt has not
  206.                                        been generated */
  207.         send_data = buffer[pkts_ackd];
  208.  
  209.         /* keep re-transmitting the packet as long as the receiver
  210.            does not acknowledge receipt (timeout occurs) */
  211.         tx_attempts = 0;
  212.         do
  213.         {
  214.             if (sendto(sock, send_data, thread_args.pkt_len, 0,
  215.               (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
  216.                 handle_error("Send Error");
  217.  
  218.             FD_ZERO(&rfds);
  219.             FD_SET(sock, &rfds);
  220.             timeout.tv_sec = TO_SEC;
  221.             timeout.tv_usec = TO_USEC;
  222.             if (select(sock+1, &rfds, NULL, NULL, &timeout) == -1)
  223.                 handle_error("Select Error");
  224.             tx_attempts++;
  225.         } while (!FD_ISSET(sock, &rfds));
  226.  
  227.         total_transmissions += tx_attempts;
  228.  
  229.         addr_len = sizeof(struct sockaddr);
  230.         bytes_read = recvfrom(sock, recv_data, DEF_ACK_PKT_LEN, 0,
  231.                 (struct sockaddr *)&server_addr, &addr_len);
  232.         recv_data[bytes_read] = '\0';
  233.         gettimeofday(&ack_time, NULL);
  234.         memcpy((void *)&gen_time, (void *)(send_data+1), sizeof(struct timeval));
  235.         if (debug_mode)
  236.         {
  237.             timersub(&gen_time, &prog_start, &gen_time);
  238.             timersub(&ack_time, &prog_start, &ack_time);
  239.  
  240.             /* times of packet generation and acknowledgement are displayed
  241.                relative to the time of sender program commencement (in s) */
  242.             printf("Seq #: %hhu; Time Generated: %.5lfs; Time ACK Recd.: %.5lfs; No. of attempts: %d\n",
  243.                     (send_data[0]),
  244.                     (gen_time.tv_sec + gen_time.tv_usec/1000000.0),
  245.                     (ack_time.tv_sec + ack_time.tv_usec/1000000.0),
  246.                     tx_attempts);
  247.         }
  248.         free(send_data); // free the memory allocated by the thread
  249.     }
  250.     free(thread_args1);
  251.     free(buffer);
  252.  
  253.     retval = pthread_join(packet_generator, NULL);
  254.     if (retval != 0)
  255.         handle_error_th(retval, "Thread Joining Error");
  256.     if (close(sock) == -1)
  257.         handle_error("Close Error");
  258.  
  259.     gettimeofday(&prog_end, NULL);
  260.     timersub(&prog_end, &prog_start, &exec_time);
  261.     throughput = thread_args.max_pkts * thread_args.pkt_len * 8 / (exec_time.tv_sec + (exec_time.tv_usec / 1000000.0)) / 1000.0; //throughput in Kbps
  262.     tx_efficiency = (double) total_transmissions / pkts_ackd;
  263.     printf("\nPacket Rate = %d, Length = %d, Throughput = %.2lf Kbps, Ratio = %.2lf\n\n",
  264.             thread_args.pkt_gen_rate, thread_args.pkt_len, throughput, tx_efficiency);
  265.     return EXIT_SUCCESS;
  266. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement