int check_notif(t_serv *udp_serv) { int n = 0; udp_serv->len = sizeof(udp_serv->cliaddr); n = timeout_recvfrom(udp_serv->sockfd, udp_serv->mesg, 1000, (struct sockaddr_in *)&udp_serv->cliaddr, 0, &udp_serv->len); if (n) return (1); return (0); }
int main(int argc, char *argv[]) { int packet_size = sizeof(packet); int nbytes; int remote_len; struct timespec cur_time; // buffer packet packet_buffer[MAXPCKTBUFSIZE]; // ACK ack_buffer[MAXPCKTBUFSIZE]; char log_line[1024]; char tmpstr[256]; time_t tmptime; int resend_cnt[MAXPCKTBUFSIZE]; memset(resend_cnt, 0, sizeof(resend_cnt)); /* check command line args. */ if(argc<7) { printf("usage : %s <server_ip> <server_port> <error rate> <random seed> <send_file> <send_log> \n", argv[0]); exit(1); } /* Note: you must initialize the network library first before calling sendto_(). The arguments are the <errorrate> and <random seed> */ init_net_lib(atof(argv[3]), atoi(argv[4])); printf("error rate : %f\n",atof(argv[3])); /* socket creation */ int sd; if((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { printf("%s: cannot create socket \n",argv[0]); exit(1); } /* get server IP address (input must be IP address, not DNS name) */ struct sockaddr_in remoteServAddr; bzero(&remoteServAddr, sizeof(remoteServAddr)); //zero the struct remoteServAddr.sin_family = AF_INET; //address family remoteServAddr.sin_port = htons(atoi(argv[2])); //sets port to network byte order remoteServAddr.sin_addr.s_addr = inet_addr(argv[1]); //sets remote IP address printf("%s: sending data to '%s:%s' \n", argv[0], argv[1], argv[2]); remote_len = sizeof(remoteServAddr); /* Open log */ FILE * sendlog = fopen(argv[6], "w"); /* Open file to send */ FILE * sendfile = fopen(argv[5], "rb"); if (sendfile) { // determine file size int fsize; char fsizechar[32]; fseek(sendfile, 0, SEEK_END); // seek to end of file fsize = ftell(sendfile); // get current file pointer fseek(sendfile, 0, SEEK_SET); // seek back to beginning of file sprintf(fsizechar, "%d", fsize); printf("file size %s \n", fsizechar); // send file size & hand shake char msg[1024]; ACK tmpack; strcpy(msg, argv[5]); strcat(msg, "\t"); strcat(msg, fsizechar); nbytes = sendto(sd, msg, sizeof(msg), 0, (struct sockaddr*)&remoteServAddr, remote_len); // get ack nbytes = timeout_recvfrom(sd, &tmpack, sizeof(ACK), (struct sockaddr*)&remoteServAddr); SWS = tmpack.rws; // resend when timed out while (!nbytes) { nbytes = sendto(sd, msg, sizeof(msg), 0, (struct sockaddr*)&remoteServAddr, remote_len); // get ack nbytes = timeout_recvfrom(sd, &tmpack, sizeof(ACK), (struct sockaddr*)&remoteServAddr); // update SWS SWS = tmpack.rws; } int seq = 0; int buf_index = seq % MAXDATABUFSIZE; int remain = fsize; int total = fsize / MAXDATABUFSIZE; if (fsize % MAXDATABUFSIZE) total += 1; int readed, toread; LAR = -1; LFS = -1; int last_frame_cnt = 0; while(LAR < total-1) { if (LFS < LAR + SWS) { buf_index = seq % MAXPCKTBUFSIZE; packet_buffer[buf_index].type = DATA_TYPE; packet_buffer[buf_index].seq = seq; toread = (MAXDATABUFSIZE) < (remain) ? (MAXDATABUFSIZE) : (remain); packet_buffer[buf_index].size = toread; readed = fread(packet_buffer[buf_index].data, sizeof(char), toread, sendfile); nbytes = sendto_(sd, &(packet_buffer[buf_index]), sizeof(packet), 0, (struct sockaddr*) &remoteServAddr, remote_len); // s/r/rs seq [freeslot] LAR LFS time strcpy(log_line, "Send\t"); sprintf(tmpstr, "%d\t\t", seq); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LAR); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFS); strcat(log_line, tmpstr); time(&tmptime); strcat(log_line, ctime(&tmptime)); // strcat(log_line, "\n"); fwrite(log_line, sizeof(char), strlen(log_line), sendlog); printf("%s", log_line); LFS++; seq++; remain -= toread; } else { nbytes = timeout_recvfrom(sd, &tmpack, sizeof(ACK), (struct sockaddr*)&remoteServAddr); // printf("nbytes: %d, tmpack.seq: %d, tmpack.rws: %d.\n", nbytes, tmpack.seq, tmpack.rws); if (nbytes) {// received if (LAR == tmpack.seq) {// duplicated, resend SWS = tmpack.rws; } if (LAR < tmpack.seq) {// update LAR, SWS LAR = tmpack.seq; SWS = tmpack.rws; } // s/r/rs seq [freeslot] LAR LFS time strcpy(log_line, "Receive\t"); sprintf(tmpstr, "%d\t", tmpack.seq); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", tmpack.freeSlots); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LAR); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFS); strcat(log_line, tmpstr); time(&tmptime); strcat(log_line, ctime(&tmptime)); //strcat(log_line, "\n"); printf("%s", log_line); fwrite(log_line, sizeof(char), strlen(log_line), sendlog); } else {// timed out, resend up to LFS if (LAR >= total - MAXPCKTBUFSIZE ) { resend_cnt[LAR - total + MAXPCKTBUFSIZE]++; if (resend_cnt[LAR - total + MAXPCKTBUFSIZE] >= 10) break; } int o = LAR + 1; int right_most = LFS < (LAR + SWS) ? LFS : (LAR + SWS); for (o = LAR + 1; o <= right_most; o++) { // printf("timed out, resend %d packet.\n", o); buf_index = o % MAXPCKTBUFSIZE; nbytes = sendto_(sd, &(packet_buffer[buf_index]), sizeof(packet), 0, (struct sockaddr*) &remoteServAddr, remote_len); // resend log strcpy(log_line, "Resend\t"); sprintf(tmpstr, "%d\t\t", packet_buffer[buf_index].seq); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LAR); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFS); strcat(log_line, tmpstr); time(&tmptime); strcat(log_line, ctime(&tmptime)); //strcat(log_line, "\n"); fwrite(log_line, sizeof(char), strlen(log_line), sendlog); printf("%s", log_line); } } } if (SWS == 0) {// solution to deadlock // probe if RWS has been reset // and reset SWS // retrieve ack printf("SWS = 0\n"); strcpy(log_line, "SWS=0\n"); fwrite(log_line, sizeof(char), strlen(log_line), sendlog); nbytes = timeout_recvfrom(sd, &tmpack, sizeof(ACK), (struct sockaddr*) &remoteServAddr); if (nbytes) { // s/r/rs seq [freeslot] LAR LFS time strcpy(log_line, "Receive\t"); sprintf(tmpstr, "%d\t", tmpack.seq); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", tmpack.freeSlots); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LAR); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFS); strcat(log_line, tmpstr); time(&tmptime); strcat(log_line, ctime(&tmptime)); // strcat(log_line, "\n"); fwrite(log_line, sizeof(char), strlen(log_line), sendlog); printf("%s", log_line); SWS = (tmpack.rws) > 0 ? (tmpack.rws) : 0; } } } fclose(sendfile); } else { printf("Failed open file %s, please retry. \n", argv[5]); } // close socket close(sd); // close log file fclose(sendlog); }
int main(int argc, char *argv[]) { int upper_limit = LFRead + MAXPCKTBUFSIZE; int free_slots = upper_limit - LFRcvd; RWS = free_slots; LAF = LFRcvd + RWS; int recv_cnt = 0; char log_line[1024]; char tmpstr[256]; time_t tmptime; // buffer packet packet_buffer[MAXPCKTBUFSIZE]; packet tmppacket; /* check command line args. */ if(argc<6) { printf("usage : %s <server_port> <error rate> <random seed> <send_file> <send_log> \n", argv[0]); exit(1); } /* Note: you must initialize the network library first before calling sendto_(). The arguments are the <errorrate> and <random seed> */ init_net_lib(atof(argv[2]), atoi(argv[3])); printf("error rate : %f\n",atof(argv[2])); /* socket creation */ int sd; if((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { printf("%s: cannot open socket \n",argv[0]); exit(1); } /* bind server port to "well-known" port whose value is known by the client */ struct sockaddr_in servAddr; bzero(&servAddr,sizeof(servAddr)); //zero the struct servAddr.sin_family = AF_INET; //address family servAddr.sin_port = htons(atoi(argv[1])); //htons() sets the port # to network byte order servAddr.sin_addr.s_addr = INADDR_ANY; //supplies the IP address of the local machine if(bind(sd, (struct sockaddr *)&servAddr, sizeof(servAddr)) <0) { printf("%s: cannot to bind port number %s \n",argv[0], argv[1]); exit(1); } /* Open log */ FILE * rcvlog = fopen(argv[5], "a"); // append trances to log /* Receive message from client */ struct sockaddr_in cliAddr; int cliLen = sizeof(cliAddr); int nbytes; int window_decreasing_flag = 0; ACK tmpack; // initial shake, recv filename and filesize from client char recvmsg[1024]; bzero(recvmsg,sizeof(recvmsg)); cliLen = sizeof(cliAddr); nbytes = recvfrom(sd, &recvmsg, sizeof (recvmsg), 0, (struct sockaddr *) &cliAddr, &cliLen); printf("Client says:\n %s \n", recvmsg); // parse file name and size char fnamechar[256]; char fsizechar[32]; int fsize; char* sec_arg = strstr(recvmsg, "\t"); strncpy(fnamechar, recvmsg, (sec_arg - recvmsg)); strcpy(fsizechar, sec_arg+1); fsize = atoi(fsizechar); int total = fsize / MAXDATABUFSIZE; if (fsize % MAXDATABUFSIZE) total += 1; // open file FILE * recvfile = fopen(argv[4], "wb"); if (recvfile) { // send ack tmpack.type = ACK_TYPE; tmpack.seq = -1; tmpack.rws = RWS; nbytes = sendto(sd, &tmpack, sizeof(ACK), 0, (struct sockaddr*)&cliAddr, cliLen); // receiving file int seq = 0; int buf_index; int skip_recv = 0; LFRead = -1; LFRcvd = -1; LAF = RWS - 1; while (LFRcvd < total - 1) { if (!skip_recv) { nbytes = timeout_recvfrom(sd, &(tmppacket), sizeof(packet), (struct sockaddr*)&cliAddr); } else { skip_recv = 0; } if (nbytes) {// received, check if out of order recv_cnt++; // force decrease receive window size if (recv_cnt >= 30 && recv_cnt <=39 ) { RWS--; if (RWS < 0) {RWS = 0;} } // arriave in order if (tmppacket.seq == LFRcvd + 1) {// update LFRcvd, send ACK, write file,update LFRead // update window LFRcvd++; seq++; upper_limit = LFRead + RWS + 1; free_slots = upper_limit - LFRcvd; // if (window_decreasing_flag == 0) // { RWS = free_slots; } LAF = LFRcvd + RWS; // construct ACK tmpack.seq = LFRcvd; tmpack.freeSlots = free_slots; tmpack.rws = RWS; // s/r/rs seq [freeslot] LFRead LFRcvd LAF time strcpy(log_line, "Receive\t"); sprintf(tmpstr, "%d\t\t", tmppacket.seq); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRead); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRcvd); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LAF); strcat(log_line, tmpstr); time(&tmptime); strcat(log_line, ctime(&tmptime)); // strcat(log_line, "\n"); fwrite(log_line, sizeof(char), strlen(log_line), rcvlog); printf("%s", log_line); // send ACK nbytes = sendto_(sd, &tmpack, sizeof(ACK), 0, (struct sockaddr*)&cliAddr, cliLen); // s/r/rs seq [freeslot] LFRead LFRcvd LAF time strcpy(log_line, "Send\t"); sprintf(tmpstr, "%d\t", tmpack.seq); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", free_slots); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRead); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRcvd); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LAF); strcat(log_line, tmpstr); time(&tmptime); strcat(log_line, ctime(&tmptime)); //strcat(log_line, "\n"); fwrite(log_line, sizeof(char), strlen(log_line), rcvlog); printf("%s", log_line); // write file fwrite((char*)&(tmppacket.data), sizeof(char), tmppacket.size, recvfile); // update LFRead LFRead = tmppacket.seq ; // equivalent to LFRread++; // scan previous received out of order packets int k = LFRcvd; for(k = LFRcvd + 1; k < LFRcvd + 1 + MAXPCKTBUFSIZE; k++) { buf_index = k % MAXPCKTBUFSIZE; if (packet_buffer[buf_index].seq == LFRcvd + 1) { // update window LFRcvd++; seq++; upper_limit = LFRead + RWS + 1; free_slots = upper_limit - LFRcvd; //if (window_decreasing_flag == 0) //{ RWS = free_slots;} // construct ACK tmpack.seq = LFRcvd; tmpack.freeSlots = free_slots; tmpack.rws = RWS; // send ACK nbytes = sendto_(sd, &tmpack, sizeof(ACK), 0, (struct sockaddr*)&cliAddr, cliLen); // s/r/rs seq [freeslot] LFRead LFRcvd LAF time strcpy(log_line, "Send\t"); sprintf(tmpstr, "%d\t", tmpack.seq); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", free_slots); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRead); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRcvd); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LAF); strcat(log_line, tmpstr); time(&tmptime); strcat(log_line, ctime(&tmptime)); // strcat(log_line, "\n"); fwrite(log_line, sizeof(char), strlen(log_line), rcvlog); printf("%s", log_line); // write file fwrite((char*)&(packet_buffer[buf_index].data), sizeof(char), packet_buffer[buf_index].size, recvfile); // update LFRead LFRead = LFRcvd; } } } if (tmppacket.seq > LFRcvd + 1) {// arrive out of order, cache packet, send duplicate ACK // as we are sending a duplicate ACK, which is exactly the previous ACK sent // just update ack.rws would be enough tmpack.rws = RWS; nbytes = sendto_(sd, &tmpack, sizeof(ACK), 0, (struct sockaddr*)&cliAddr, cliLen); // receive log strcpy(log_line, "Receive\t"); sprintf(tmpstr, "%d\t\t", tmppacket.seq); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRead); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRcvd); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LAF); strcat(log_line, tmpstr); time(&tmptime); strcat(log_line, ctime(&tmptime)); // strcat(log_line, "\n"); fwrite(log_line, sizeof(char), strlen(log_line), rcvlog); printf("%s", log_line); // send duplicate ACK log // s/r/rs seq [freeslot] LFRead LFRcvd LAF time strcpy(log_line, "Send\t"); sprintf(tmpstr, "%d\t", tmpack.seq); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", free_slots); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRead); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRcvd); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LAF); strcat(log_line, tmpstr); time(&tmptime); strcat(log_line, ctime(&tmptime)); //strcat(log_line, "\n"); fwrite(log_line, sizeof(char), strlen(log_line), rcvlog); printf("%s", log_line); // buffer out of order packet received buf_index = tmppacket.seq % MAXPCKTBUFSIZE; packet_buffer[buf_index].seq = tmppacket.seq; packet_buffer[buf_index].size = tmppacket.size; packet_buffer[buf_index].type = tmppacket.type; strcpy(packet_buffer[buf_index].data, tmppacket.data); } if (tmppacket.seq < LFRcvd + 1) {// packets alreadly received and buffered, discard ; } } // decrease rws // if (recv_cnt == 30) window_decreasing_flag = 1; // handle situation when RWS is 0 if (RWS == 0) {// RWS decreased to 0 printf("RWS = 0!!!!!\n"); strcpy(log_line, "RWS = 0!!!!!!!!!!\n"); fwrite(log_line, sizeof(char), strlen(log_line), rcvlog); printf("window_decreasing_flag = %d\n", window_decreasing_flag); if (1) {// reset flag and sleep 10 ms // window_decreasing_flag = 0; receiver_sleep(); RWS = 6; // send ACK do { tmpack.rws = RWS; nbytes = sendto_(sd, &tmpack, sizeof(ACK), 0, (struct sockaddr*)&cliAddr, cliLen); // s/r/rs seq [freeslot] LFRead LFRcvd LAF time strcpy(log_line, "Send\t"); sprintf(tmpstr, "%d\t", seq); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", free_slots); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRead); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LFRcvd); strcat(log_line, tmpstr); sprintf(tmpstr, "%d\t", LAF); strcat(log_line, tmpstr); time(&tmptime); strcat(log_line, ctime(&tmptime)); //strcat(log_line, "\n"); fwrite(log_line, sizeof(char), strlen(log_line), rcvlog); printf("%s", log_line); nbytes = timeout_recvfrom(sd, &tmppacket, sizeof(packet), (struct sockaddr*)&cliAddr); }while(!nbytes); window_decreasing_flag = 0; skip_recv = 1; } } } fclose(recvfile); } else { printf("Failed open file %s, please retry. \n", fnamechar); } // close log file fclose(rcvlog); // close socket close(sd); }