Last active
November 30, 2017 18:10
-
-
Save kehanlu/b0cb64981027d85cadedf1ae130dad63 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define SRV_IP "127.0.0.1" | |
#include <arpa/inet.h> | |
#include <netinet/in.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <unistd.h> | |
#include <string.h> | |
#define BUFLEN 512 | |
#define NPACK 50 | |
#define PORT 9930 | |
#define BUF_SIZE 1000 | |
#define SLOW_START 1 | |
#define C_AVOID 2 | |
/* diep(), #includes and #defines like in the server */ | |
struct sockaddr_in initial(){ | |
struct sockaddr_in si_other; | |
memset((char *) &si_other, 0, sizeof(si_other)); | |
si_other.sin_family = AF_INET; | |
si_other.sin_port = htons(PORT); | |
if (inet_aton(SRV_IP, &si_other.sin_addr)==0){ | |
fprintf(stderr, "inet_aton() failed\n"); | |
return si_other; | |
} | |
return si_other; | |
} | |
int connect_socket(void){ | |
int s; | |
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) | |
perror("socket"); | |
return s; | |
} | |
void close_socket(int s){ | |
close(s); | |
} | |
int count = 1; | |
void print_cwnd(int cwnd){ | |
printf("%d: =========CWND = %d========\n", count, cwnd); | |
count++; | |
} | |
void print_duplicate(){ | |
printf("%d:=========3 duplicate ack========\n",count); | |
count++; | |
} | |
void print_timeout(){ | |
printf("%d:=========Time out========\n",count); | |
count++; | |
} | |
int main(void){ | |
struct sockaddr_in si_other, recv_ip; | |
int s, i, slen=sizeof(si_other), rlen = sizeof(recv_ip); | |
char buf[BUFLEN]; | |
struct timeval tv; | |
fd_set readfds; | |
si_other = initial(); | |
s = connect_socket(); | |
int send_buffer[NPACK + 1]; | |
int cwnd = 1; | |
double cwnd_double = 1.0; | |
int lastByteSent = 0; //已經送出去的 | |
int lastByteAcked = 0; //已經沒問題的 | |
int ssthresh = 10; | |
int pre_acked; | |
int acked = 0; | |
int duplicate_ack = 0; | |
int state = SLOW_START; | |
for(i = 0; i < NPACK + 1; i++){ | |
send_buffer[i] = i; | |
} | |
/* Insert your codes below */ | |
pre_acked = 1; | |
acked = 1; | |
tv.tv_sec = 1; | |
tv.tv_usec = 0; | |
int window = 1; | |
int timeout = 0; | |
int count_C_AVOID = 1; | |
const int FAST_RECOVERY = 3; | |
for(lastByteSent = 0; lastByteSent < NPACK && lastByteSent+window < NPACK+2;){ | |
for(window = 1; window < cwnd+1;window++){ //window | |
memset(buf, 0, BUFLEN); | |
sprintf(buf, "%d", send_buffer[lastByteSent+window]); | |
sendto(s, buf, BUFLEN, 0,(struct sockaddr*) &si_other,(socklen_t) slen); | |
//printf("\n**********\nlastByteSent:%d\n",lastByteSent); | |
//printf("send: %d, window:%d,cwnd:%d\n,ssthresh:%d\n",lastByteSent+window,window,cwnd,ssthresh); | |
FD_ZERO(&readfds); | |
FD_SET(s, &readfds); | |
select(s + 1, &readfds, NULL, NULL, &tv);//開始監聽0.333333秒 | |
//printf("pre_acked:%d ",pre_acked); | |
if(!FD_ISSET(s, &readfds) ){ | |
//packet loss | |
timeout++; | |
//loss 3 time (=1sec) | |
//cwnd-window < 3 (if >3 will receive 3 duplicate ACK) | |
if(timeout == 4 || cwnd-window < 3){ | |
//set | |
timeout = 0; | |
ssthresh = cwnd/2; | |
cwnd = 1; | |
duplicate_ack = 0; | |
//goto | |
lastByteSent = lastByteAcked; | |
//change state | |
state = SLOW_START; | |
print_timeout(); | |
break; | |
} | |
}else{ | |
//packet receive! | |
recvfrom(s, buf, BUFLEN, 0, (struct sockaddr*) &recv_ip, (socklen_t*) &rlen); | |
acked = atoi(buf); | |
printf("ack:%d \n",acked); | |
//set | |
timeout = 0; | |
if(state == SLOW_START){ | |
//SLOW_START | |
if(acked == pre_acked+1){ | |
//NEW ACK | |
//set | |
cwnd = cwnd + 1; | |
duplicate_ack = 0; | |
pre_acked = acked; | |
//goto | |
lastByteAcked = acked-1; | |
lastByteSent++; | |
print_cwnd(cwnd); | |
//change state | |
if(cwnd >= ssthresh) | |
state = C_AVOID; | |
break; | |
}else if(acked == pre_acked){ | |
// DUPLICATE ACK | |
//set | |
duplicate_ack++; | |
if(duplicate_ack == 3){ | |
// 3 duplicate ack | |
//set | |
ssthresh = (cwnd+1) / 2; | |
cwnd = ssthresh + 3; | |
duplicate_ack = 0; | |
//goto | |
lastByteAcked = acked-1; | |
lastByteSent = lastByteAcked; | |
//change state | |
state = FAST_RECOVERY; | |
print_duplicate(); | |
break; | |
} | |
print_cwnd(cwnd); | |
} | |
}else if(state == C_AVOID){ | |
//C_AVOID | |
if(acked == pre_acked+1){ | |
//NEW ACK | |
//set | |
if(count_C_AVOID == cwnd){ | |
cwnd = cwnd + 1; | |
count_C_AVOID = 1; | |
}else{ | |
count_C_AVOID++; | |
} | |
duplicate_ack = 0; | |
pre_acked = acked; | |
//goto | |
lastByteAcked = acked-1; | |
lastByteSent++; | |
print_cwnd(cwnd); | |
break; | |
}else if(acked == pre_acked){ | |
//DUPLICATE ACK | |
//set | |
duplicate_ack++; | |
if(duplicate_ack == 3){ | |
// 3 duplicate ack | |
ssthresh = (cwnd+1) / 2; | |
cwnd = ssthresh + 3; | |
duplicate_ack = 0; | |
//goto | |
lastByteAcked = acked-1; | |
lastByteSent = lastByteAcked; | |
//change state | |
state = FAST_RECOVERY; | |
print_duplicate(); | |
break; | |
} | |
print_cwnd(cwnd); | |
} | |
}else if(state == FAST_RECOVERY){ | |
//FAST_RECOVERY | |
if(acked == pre_acked+1){ | |
//NEW ACK | |
//set | |
cwnd = ssthresh+3; //重傳後會有三次dupACK | |
duplicate_ack = 0; | |
pre_acked = acked; | |
//goto | |
lastByteAcked = acked-1; | |
lastByteSent++; | |
//change state | |
state = C_AVOID; | |
print_cwnd(cwnd); | |
break; | |
}else{ | |
//goto | |
lastByteSent = acked-1; | |
pre_acked = acked; | |
print_cwnd(cwnd); | |
break; | |
} | |
}//end of if (state) | |
}//end of if (receive packet) | |
}//end of for | |
}//end of for | |
/* Insert your codes above */ | |
close_socket(s); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment