int Task2(int speed, int delay, char* filename) { pkg myPackage; msg* haos; msg t, aux; long bdp, window; int fdIn, count; char infoBuffer[PKGSIZE]; /* buffer citire fisier */ int i, packNum = 0, timeout; TLista bufferMesaje; /* buffer pachete */ int k, res; /* setare varibaila timeout */ if(2 * delay > 1000) timeout = 2 * delay; else timeout = 1000; bdp = speed * delay * 1000; window = bdp / (FRAMESIZE * 8); printf("[SENDER]Window = %ld frames\n", window); printf("[SENDER]Sender starts.\n"); printf("[SENDER]Filename=%s, task_index=%d, speed=%d, delay=%d\n", filename, 2, speed, delay); /* deschidere fisier */ fdIn = open(filename, O_RDONLY); if(fdIn < 0) { perror("File openning error.\n"); return -1; } /* pachet initializare retea */ memset(t.payload, 0, sizeof(t.payload)); memset(myPackage.payload, 0, sizeof(myPackage.payload)); myPackage.messageType = TYPE_INIT; myPackage.packNum = window; memcpy(myPackage.payload, filename, strlen(filename)); memcpy(t.payload, &myPackage, sizeof(pkg)); t.len = strlen(myPackage.payload) + 1; printf("[SENDER]Sending init message.\n"); if(send_message(&t) < 0) { fflush(stdin); perror("Error sending init message.\n"); fflush(stdin); return -1; } /* retrimit pachetul pana ce sunt sigur ca si receiverul este initializat */ while (recv_message_timeout(&aux, timeout) < 0) { fflush(stdin); printf("[SENDER] receive error\nWill attempt to resend.\n"); fflush(stdin); send_message(&t); } printf("[SENDER] Got reply with payload: %s\n", t.payload); /* trimitere efectiva mesaje */ window--;/* se vor trimite mesajele de la 0 la window - 1*/ printf("-----Commence filereading.-----\n"); count = read(fdIn, infoBuffer, PKGSIZE); while(count > 0) { /* pregatire pachet date */ memset(t.payload, 0, sizeof(t.payload)); memset(myPackage.payload, 0, sizeof(myPackage.payload)); /* actualizare tip pachet + numar de ordine */ myPackage.messageType = TYPE_INFO; myPackage.packNum = packNum++; if(count < PKGSIZE) myPackage.messageType = TYPE_END; memcpy(myPackage.payload, infoBuffer, count); memcpy(t.payload, &myPackage, sizeof(myPackage)); printf("[SENDER]Message number %i has been sent.\n", myPackage.packNum); t.len = count + 1; /* creare duplicat mesaj pentru a il salva in buffer */ haos = mesageDup(&t); send_message(&t); InsSfL(&bufferMesaje, haos); if(window == 0) { /* daca (N)ACK-ul este primit la timp */ if(recv_message_timeout(&aux, timeout) > 0) { /* cat timp primim NACK-uri, retrimitem pachetele in cauza */ while((*(pkg*)aux.payload).messageType == TYPE_NACK) { /* daca s-a primit NACK pentru un pachet care inca nu a fost trimis */ if(k >= packNum) break; /* retinem numarul de ordine al pachetului pentru care s-a primit NACK*/ k = (*(pkg*)aux.payload).packNum; printf("[SENDER]Message %i has been resent.\n", k); /* retrimit pachetul */ res = send_message(getPackNum(&bufferMesaje, k)); if(res < 0) { perror("RESEND error\n"); return -1; } recv_message_timeout(&aux, timeout); } /* elimin pachetul confirmat din buffer */ printf("[SENDER]Eliminating package %i from queue.\n", (*(pkg*)aux.payload).packNum); if(ElimPackNum(&bufferMesaje,(*(pkg*)aux.payload).packNum) < 0) { printf("[SENDER]Error eliminating package.\n"); return -1; } } /* Daca timeout-ul a fost atins, retrimitem tot ce avem in buffer*/ else { printf("[SENDER]Timeout reached.\n"); do { printf("[SENDER]Attempting resend.\n"); for(i = 0; i < ListLength(&bufferMesaje); i++) { send_message(getindex(&bufferMesaje,i)); } } while(recv_message_timeout(&aux, timeout) < 0); } } else window--; count = read(fdIn, infoBuffer, PKGSIZE); } /* s-a incheiat citirea din fisier; trimitem un pachet final */ printf("[SENDER]Filereading has ended. Last file is: %i\n", packNum); myPackage.messageType = TYPE_END; myPackage.packNum = packNum++; memcpy(t.payload, &myPackage, sizeof(myPackage)); t.len = 0; haos = mesageDup(&t); send_message(&t); InsSfL(&bufferMesaje, haos); send_message(&t); /* asteptam sa primim confirmarea tuturor pachetelor trimise */ /* NOTA: mod de operare similar cu ce avem mai sus */ printf("[SENDER]Will attempt resend for all the messages left in the buffer.\n"); while(ListLength(&bufferMesaje) >= 1) { /* daca (N)ACK-ul este primit la timp */ if(recv_message_timeout(&aux, timeout) > 0) { /* cat timp primim NACK-uri, retrimitem pachetele aferente */ while((*(pkg*)aux.payload).messageType != TYPE_ACK) { printf("[SENDER]Message %i has been resent.\n", k); k = (*(pkg*)aux.payload).packNum; if(k >= packNum) break; res = send_message(getPackNum(&bufferMesaje, k)); if(res < 0) { AfisareL(&bufferMesaje); printf("[SENDER]RESEND error.\n"); return -1; } recv_message_timeout(&aux, timeout); } /* cand am primit un ACK, eliminam pachetul respectiv din buffer*/ printf("[SENDER]Eliminating package %i from queue.\n", (*(pkg*)aux.payload).packNum); if(ElimPackNum(&bufferMesaje,(*(pkg*)aux.payload).packNum) < 0) { /* eroare care nu afecteaza puternic activitatea programului, dar trebuie semnalata */ printf("[SENDER]Error eliminating package.\n"); } } else { printf("[SENDER]Timeout reached.\n"); } /* daca a mai ramas doar mesajul de final, ne oprim */ if(ListLength(&bufferMesaje) == 1) if( (*(pkg*)(bufferMesaje->info).payload).messageType == TYPE_END) break; } printf("[SENDER]Job done.\n"); close(fdIn); return 0; }
int main(int argc, char *argv[]) { char *filename; int task_index, speed, delay, filesize; int i, fd, timeout, res, COUNT; int bdp, window, FRAME_SIZE; char read_buffer[MSGSIZE]; struct stat f_status; task_index = atoi(argv[1]); filename = argv[2]; speed = atoi(argv[3]); delay = atoi(argv[4]); printf("[SENDER] Sender starts.\n"); printf("[SENDER] Filename=%s, task_index=%d, speed=%d, delay=%d\n", filename, task_index, speed, delay); /* miliseconds for delay & megabits for speed */ bdp = speed * delay * 1000; printf("[SENDER] BDP = %d b(bits).\n", bdp); fd = open(filename, O_RDONLY); fstat(fd, &f_status); filesize = (int) f_status.st_size; printf("[SENDER] File size: %d\n", filesize); /* miliseconds for timeout */ if(2*delay > 1000) timeout = 2*delay; else timeout = 1000; printf("[SENDER] timeout = %d\n", timeout); init(HOST, PORT1); if(task_index == 0 || task_index == 1) { msg t; my_pkt p; int SCAN, bsize; queue *buffer; buffer = (queue *) malloc(sizeof(queue)); create_queue(buffer, sizeof(msg)); FRAME_SIZE = MSGSIZE + 4; printf("[SENDER] Each frame has %d B(bytes).\n", FRAME_SIZE); COUNT = filesize / FRAME_SIZE; printf("[SENDER] Gonna send %d frames.\n", COUNT); /* window = number of frames in the 'network', unacked */ window = bdp / (FRAME_SIZE * BITS_NO); printf("[SENDER] window = %d frames\n", window); /* Len in message = size(msg payload) = amount of data in the my_pkt structure = size(type) + data in (pkt payload) = sizeof(int) + number of used bytes in (pkt payload) */ /* Gonna send filename - SEQ = -2 message */ memset(t.payload, 0, sizeof(t.payload)); memset(p.payload, 0, sizeof(p.payload)); p.SEQ = -2; memcpy(p.payload, filename, strlen(filename)); t.len = sizeof(int) + strlen(filename) + 1; memcpy(t.payload, &p, t.len); while(1) { /* send msg */ while(1) { res = send_message(&t); if (res < 0) { perror("[SENDER] Send error. Resending"); continue; } break; } printf("[SENDER] Filename sent.\n"); /* Wait for filename ACK */ if (recv_message_timeout(&t, timeout) < 0) { perror("[SENDER] Receive error: TIMEOUT. Resending"); continue; } p = *((my_pkt *) t.payload); if (p.SEQ != -2) { perror("[SENDER] Receive error: WRONG ACK. Resending"); continue; } printf("[SENDER] Got reply with ACK: %d (Filename)\n", p.SEQ); break; } /* Gonna send filesize - SEQ = -1 message */ memset(t.payload, 0, sizeof(t.payload)); memset(p.payload, 0, sizeof(p.payload)); p.SEQ = -1; memcpy(p.payload, &filesize, sizeof(int)); t.len = sizeof(int) * 2; memcpy(t.payload, &p, t.len); while(1) { /* send msg */ while(1) { res = send_message(&t); if (res < 0) { perror("[SENDER] Send error. Resending"); continue; } break; } printf("[SENDER] Filesize sent.\n"); /* Wait for filesize ACK */ if (recv_message_timeout(&t, timeout) < 0) { perror("[SENDER] Receive error: TIMEOUT. Resending"); continue; } p = *((my_pkt *) t.payload); if (p.SEQ != -1) { perror("[SENDER] Receive error: WRONG ACK. Resending"); continue; } printf("[SENDER] Got reply with ACK: %d (Filesize)\n", p.SEQ); break; } /* Send file contents - (SEQ = 0 -> COUNT) messages */ int seq = 0; /* Fill the link = send window messages */ for (i = 0; i < window; i++) { if((SCAN = read(fd, read_buffer, MSGSIZE - sizeof(int))) > 0) { memset(t.payload, 0, sizeof(t.payload)); memset(p.payload, 0, sizeof(p.payload)); p.SEQ = seq; memcpy(p.payload, read_buffer, SCAN); t.len = sizeof(int) + SCAN; memcpy(t.payload, &p, t.len); printf("[SENDER] Sending message with SEQ: %d\n", seq); /* put msg in buffer */ enqueue(buffer, &t); /* send msg */ while(1) { res = send_message(&t); if (res < 0) { perror("[SENDER] Send error. Resending"); continue; } break; } seq++; } else break; } /* From now on, ack clocking, i.e., a new ack will inform us about the space released in the link */ while(1) { /* wait for ACK */ if (recv_message_timeout(&t, timeout) < 0) { perror("[SENDER] Receive error: TIMEOUT. Resending buffer"); bsize = buffer->size; while(bsize) { /* clear msg from buffer */ dequeue(buffer, &t); /* send msg */ while(1) { res = send_message(&t); if (res < 0) { perror("[SENDER] Send error. Resending"); continue; } break; } /* reput msg in buffer, in case it will be lost again */ enqueue(buffer, &t); bsize--; } continue; } else { p = *((my_pkt *) t.payload); printf("[SENDER] Got reply with ACK: %d\n", p.SEQ); /* clear succesfully sent msg from buffer */ dequeue(buffer, &t); if((SCAN = read(fd, read_buffer, MSGSIZE - sizeof(int))) > 0) { memset(t.payload, 0, sizeof(t.payload)); memset(p.payload, 0, sizeof(p.payload)); p.SEQ = seq; memcpy(p.payload, read_buffer, SCAN); t.len = sizeof(int) + SCAN; memcpy(t.payload, &p, t.len); printf("[SENDER] Sending message with SEQ: %d\n", seq); /* put msg in buffer */ enqueue(buffer, &t); /* send msg */ while(1) { res = send_message(&t); if (res < 0) { perror("[SENDER] Send error. Resending"); continue; } break; } seq++; } else if(buffer->size == 0) break; } } destroy_queue(buffer); free(buffer); } printf("[SERVER] File transfer has ended.\n"); close(fd); return 0; }