Skip to content

Instantly share code, notes, and snippets.

@kehanlu
Last active November 30, 2017 18:10
Show Gist options
  • Save kehanlu/b0cb64981027d85cadedf1ae130dad63 to your computer and use it in GitHub Desktop.
Save kehanlu/b0cb64981027d85cadedf1ae130dad63 to your computer and use it in GitHub Desktop.
#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