Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Implementation of the Stop-and-Wait Protocol
- /**************************SENDER PROGRAM**********************************
- * Author:- Parth Joshi
- * Roll No:- CS09B051
- *
- * USAGE:- ./sender [-s <RECEIVER_URL>] [-p <PORT_NO>] [-l <PACKET_LENGTH>]
- [-r <PACKET_GEN_RATE>] [-n <MAX_PACKETS>] [-d]
- * The default values of the above parameters are taken to be:-
- * Server address -- localhost
- * Server port -- 22051
- * Packet length -- 512 bytes
- * Packet generation rate -- 10 packets/second
- * Maximum no of packets -- 400
- * NODEBUG mode
- **************************************************************************/
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/select.h>
- #include <sys/time.h>
- #include <netinet/in.h>
- #include <arpa/inet.h> //for inet_ntoa()
- #include <netdb.h> //for struct hostent, gethostbyname()
- #include <stdio.h>
- #include <unistd.h>
- #include <errno.h>
- #include <string.h>
- #include <math.h> //for ceil()
- #include <stdlib.h>
- #include <pthread.h>
- #define TO_SEC 0
- #define TO_USEC 100*1000 //timeout limit in ms
- #define DEF_RECV_ADDR "localhost"
- #define DEF_RECV_PORT 22051
- #define DEF_PKT_LEN 512
- #define DEF_PKT_GEN_RATE 10
- #define DEF_MAX_PKTS 400
- #define DEF_ACK_PKT_LEN 60
- #define DEF_SEQ_BITS 8
- /* error handling macros */
- // handling thread errors (which do not set errno)
- #define handle_error_th(err, msg) \
- do { errno = err; perror(msg); exit(EXIT_FAILURE); } while(0)
- //handling other system call errors (which set errno)
- #define handle_error(msg) \
- do { perror(msg); exit(EXIT_FAILURE); } while(0)
- char **buffer = NULL; /* the sender buffer used to store packets as they
- are generated */
- // char **front = NULL, **back = NULL /* pointers to mark the beginning
- // and end of the queue */
- typedef struct packet_generator_args
- {
- int max_pkts;
- int pkt_len;
- int pkt_gen_rate;
- } pktgen_args;
- /*void push_into_buffer(packet_t *pkt)
- {
- }
- packet_t pop_from_buffer()
- {
- }*/
- /* uniform distribution on (0..1] */
- double drand()
- {
- return (rand()+1.0)/(RAND_MAX+1.0);
- }
- /* normal distribution, centered on 0, std dev 1 using Box-Muller transform */
- double random_normal()
- {
- return sqrt(-2*log(drand())) * cos(2*M_PI*drand());
- }
- /* returns a random wait time sampled from a normal distribution with
- mean time determined according to the parameter pkt_gen_rate and
- std dev calculated as 5% of the mean value */
- void random_wait(int pkt_gen_rate, struct timeval *rwait)
- {
- struct timeval dev, mean;
- mean.tv_sec = dev.tv_sec = 0;
- mean.tv_usec = 1000000/pkt_gen_rate;
- dev.tv_usec = (suseconds_t)(0.05 * mean.tv_usec * random_normal());
- timeradd(&mean, &dev, rwait);
- }
- /* generates and buffers packets at a mean rate given by the
- pkt_gen_rate field of its argument; runs in a separate thread */
- void *generate_packets(void *arg)
- {
- pktgen_args *opts = (pktgen_args *)arg; // error occurs after execution of this line
- buffer = (char **)calloc((size_t)opts->max_pkts, sizeof(char *));
- if (buffer == NULL)
- handle_error("Calloc Error");
- //front = back = buffer;
- int i;
- struct timeval gen_time, wait_time;
- //packet_t *new;
- srand(time(NULL));
- for (i=0; i<opts->max_pkts; i++)
- {
- if ((buffer[i] = calloc((size_t)opts->pkt_len, sizeof(char))) == NULL)
- handle_error("Calloc Error");
- buffer[i][0] = i%(1<<DEF_SEQ_BITS);
- gettimeofday(&gen_time, NULL);
- memcpy((void *)(buffer[i]+1), &gen_time, sizeof(struct timeval));
- random_wait(opts->pkt_gen_rate, &wait_time);
- if (select(0, NULL, NULL, NULL, &wait_time) == -1)
- handle_error("Wait Error");
- }
- return 0;
- }
- int main(int argc,char *argv[])
- {
- pktgen_args thread_args;
- thread_args.pkt_len = DEF_PKT_LEN;
- thread_args.pkt_gen_rate = DEF_PKT_GEN_RATE;
- thread_args.max_pkts = DEF_MAX_PKTS;
- short server_port = DEF_RECV_PORT;
- char serv_host_name[30] = DEF_RECV_ADDR;
- char debug_mode = 0;
- int tx_attempts, pkts_ackd, total_transmissions;
- double tx_efficiency, throughput;
- int sock, addr_len;
- struct sockaddr_in server_addr;
- struct hostent *host;
- unsigned char *send_data, recv_data[DEF_ACK_PKT_LEN];
- const char USAGE_STR[] = "USAGE: ./sender [-s <RECEIVER_URL>] [-p <PORT_NO>] [-l <PACKET_LENGTH>] [-r <PACKET_GEN_RATE>] [-n <MAX_PACKETS>] [-d]\n";
- int retval, bytes_read, i;
- fd_set rfds;
- struct timeval prog_start, prog_end, exec_time;
- struct timeval gen_time, ack_time, timeout;
- //command line options
- for (i=1; i<10; i+=2)
- {
- if (argc <= i+1)
- break;
- if (strcmp(argv[i], "-p") == 0)
- server_port = atoi(argv[i+1]);
- else if (strcmp(argv[i], "-s") == 0)
- strcpy(serv_host_name, argv[i+1]);
- else if (strcmp(argv[i], "-l") == 0)
- thread_args.pkt_len = atoi(argv[i+1]);
- else if (strcmp(argv[i], "-r") == 0)
- thread_args.pkt_gen_rate = atoi(argv[i+1]);
- else if (strcmp(argv[i], "-n") == 0)
- thread_args.max_pkts = atoi(argv[i+1]);
- else
- {
- printf("%s", USAGE_STR);
- exit(EXIT_FAILURE);
- }
- }
- if (argc == i+1)
- {
- if (strcmp(argv[i], "-d") == 0)
- debug_mode = 1;
- else
- {
- printf("%s", USAGE_STR);
- exit(EXIT_FAILURE);
- }
- }
- gettimeofday(&prog_start, NULL);
- host = (struct hostent *) gethostbyname(serv_host_name);
- if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
- handle_error("Socket Error");
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(server_port);
- server_addr.sin_addr = *((struct in_addr *)host->h_addr);
- memset(&(server_addr.sin_zero),0,8);
- //generate data packets at the rate of thread_args.pkt_gen_rate
- pthread_t packet_generator;
- pktgen_args *thread_args1 = (pktgen_args *)malloc(sizeof(pktgen_args));
- memcpy((void *)thread_args1, (void *)&thread_args, sizeof(pktgen_args));
- retval = pthread_create(&packet_generator, NULL, &generate_packets, (void *)thread_args1);
- if (retval != 0)
- handle_error_th(retval, "Thread Creation Error");
- for (pkts_ackd = 0, total_transmissions = 0; pkts_ackd < thread_args.max_pkts; pkts_ackd++)
- {
- while (!buffer[pkts_ackd]); /* wait as long as the next pkt has not
- been generated */
- send_data = buffer[pkts_ackd];
- /* keep re-transmitting the packet as long as the receiver
- does not acknowledge receipt (timeout occurs) */
- tx_attempts = 0;
- do
- {
- if (sendto(sock, send_data, thread_args.pkt_len, 0,
- (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
- handle_error("Send Error");
- FD_ZERO(&rfds);
- FD_SET(sock, &rfds);
- timeout.tv_sec = TO_SEC;
- timeout.tv_usec = TO_USEC;
- if (select(sock+1, &rfds, NULL, NULL, &timeout) == -1)
- handle_error("Select Error");
- tx_attempts++;
- } while (!FD_ISSET(sock, &rfds));
- total_transmissions += tx_attempts;
- addr_len = sizeof(struct sockaddr);
- bytes_read = recvfrom(sock, recv_data, DEF_ACK_PKT_LEN, 0,
- (struct sockaddr *)&server_addr, &addr_len);
- recv_data[bytes_read] = '\0';
- gettimeofday(&ack_time, NULL);
- memcpy((void *)&gen_time, (void *)(send_data+1), sizeof(struct timeval));
- if (debug_mode)
- {
- timersub(&gen_time, &prog_start, &gen_time);
- timersub(&ack_time, &prog_start, &ack_time);
- /* times of packet generation and acknowledgement are displayed
- relative to the time of sender program commencement (in s) */
- printf("Seq #: %hhu; Time Generated: %.5lfs; Time ACK Recd.: %.5lfs; No. of attempts: %d\n",
- (send_data[0]),
- (gen_time.tv_sec + gen_time.tv_usec/1000000.0),
- (ack_time.tv_sec + ack_time.tv_usec/1000000.0),
- tx_attempts);
- }
- free(send_data); // free the memory allocated by the thread
- }
- free(thread_args1);
- free(buffer);
- retval = pthread_join(packet_generator, NULL);
- if (retval != 0)
- handle_error_th(retval, "Thread Joining Error");
- if (close(sock) == -1)
- handle_error("Close Error");
- gettimeofday(&prog_end, NULL);
- timersub(&prog_end, &prog_start, &exec_time);
- 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
- tx_efficiency = (double) total_transmissions / pkts_ackd;
- printf("\nPacket Rate = %d, Length = %d, Throughput = %.2lf Kbps, Ratio = %.2lf\n\n",
- thread_args.pkt_gen_rate, thread_args.pkt_len, throughput, tx_efficiency);
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement