This repository has been archived by the owner on Nov 9, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
send.c
154 lines (151 loc) · 4.92 KB
/
send.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "lib.h"
#include "link_emulator/lib.h"
#include "lib.h"
#define HOST "127.0.0.1"
#define PORT 10000
#define FRAME_SIZE 1404
#define BITS_NO 8
int main(int argc, char** argv) {
msg t;
my_pkt p;
long fd, count, filesize;
struct stat f_status;
char buffer[MSGSIZE];
long bandwidth, delay, window;
init(HOST, PORT);
printf("[SENDER] File to send: %s\n", argv[1]);
/* Retinem descriptorul fisierului deschis
reprezentat de parametrul transmis */
fd = open(argv[1], O_RDONLY);
fstat(fd, &f_status);
/* Viteza de transmisie (V) - bandwidth */
bandwidth = atol(argv[2]);
/* Timpul de propagare (TP) - delay */
delay = atol(argv[3]);
/* Cantitatea de informatie aflata in zbor la un anumit moment de timp */
long bdp = bandwidth * delay * 1000;
/* window reprezinta numarul maxim de
cadre neconfirmate la orice moment de timp*/
window = bdp / (FRAME_SIZE * BITS_NO);
/* Retinem dimensiunea fisierului care urmeaza sa-l transmitem */
filesize = (long)f_status.st_size;
memset(t.payload, 0, sizeof(t.payload));
memset(p.payload, 0, sizeof(p.payload));
// TYPE1 reprezinta trimiterea pentru numele de fisier (are valoarea 1)
p.type = TYPE1;
memcpy(p.payload, argv[1], strlen(argv[1]));
t.len = sizeof(int) + strlen(argv[1]);
memcpy(t.payload, &p, t.len);
/* Trimitem numele fisierului de transmis */
send_message(&t);
/* ASteptam ACK-ul pentru numele fisierului */
if (recv_message(&t) < 0) {
perror("[SENDER] Receive error");
return -1;
}
/* Verificam confirmarea din recv.c (p.type este TYPE4) */
p = *((my_pkt *) t.payload);
if (p.type != TYPE4) {
perror("[SENDER] Receive error");
return -1;
}
memset(t.payload, 0, sizeof(t.payload));
memset(p.payload, 0, sizeof(p.payload));
/* Vom trimite dimensiunea fisierului - TYPE2 message */
p.type = TYPE2;
/* Adaugam lungimea fisierului */
memcpy(p.payload, &filesize, sizeof(int));
t.len = sizeof(int) * 2;
/* Se copiaza bit cu bit structura p in t.payload */
memcpy(t.payload, &p, t.len);
send_message(&t);
/* Asteptam ACK pentru primirea lungimii fisierului */
if (recv_message(&t) < 0) {
perror("[SENDER] Receive error");
return -1;
}
/* Verificam ACK TYPE4 pentru confirmarea primirii mesajului */
p = *((my_pkt *)t.payload);
if (p.type != TYPE4) {
perror("[SENDER] Receive error");
return -1;
}
/* Trimitem continutul fisierului - TYPE3 MESSAGES */
long frames = 0;
msg messages[COUNT];
/* Cat timp citim din fisier, salvam mesajele de trimis intr-un buffer
pentru a le trimite cu ajutorul ferestrei glisante */
while ((count = read(fd, buffer, MSGSIZE - sizeof(int))) > 0) {
memset(messages[frames].payload, 0, sizeof(messages[frames].payload));
memset(p.payload, 0, sizeof(p.payload));
/* Trimitem continutul fisierului - TYPE3 MESSAGES */
p.type = TYPE3;
memcpy(p.payload, buffer, count);
messages[frames].len = sizeof(int) + count;
memcpy(messages[frames].payload, &p, messages[frames].len);
frames++;
}
long res = 0, i;
/* Facem min dintre window si numarul de pachete,daca exista mai puține pachete
decât dimensiunea window, încearcă sa trimita pachete care nu exista */
if (frames < window) {
window = frames;
}
/* Punem pe fir un numar de cadre egal cu dimensiunea ferestrei */
for (i = 0; i < window; i++) {
res = send_message(&messages[i]);
if (res < 0) {
perror("[SENDER] Send error. Exiting.\n");
return -1;
}
}
/* Asteptam confirmarile deoarece pentru fiecare confirmare putem
sa introducem un nou cadru in retea. (putem trimite urmatorul cadrul) */
long count_window = window;
for (i = 0; i < frames - window; i++) {
/* Asteptam ACK pentru primirea mesajului din buffer */
res = recv_message(&t);
if (res < 0) {
perror("[SENDER] Receive error. Exiting.\n");
return -1;
}
p = *((my_pkt *)t.payload);
/* Verificam ACK TYPE4 pentru confirmarea primirii mesajului */
if (p.type != TYPE4) {
perror("[SENDER] Receive error");
return -1;
}
/* Introducem un nou cadru in retea, putem trimite urmatorul cadru */
res = send_message(&messages[count_window]);
if (res < 0) {
perror("[SENDER] Send error. Exiting.\n");
return -1;
}
count_window++;
}
/* Asteptam ACK-urile pentru celelalte window mesaje care au ramas pe fir */
for (i = 0; i < window; i++) {
memset(t.payload, 0, sizeof(t.payload));
res = recv_message(&t);
if (res < 0) {
perror("[SENDER] Receive error. Exiting.\n");
return -1;
}
p = *((my_pkt *)t.payload);
/* Verificam daca s-au trimis toate pachetele din fisier cu
confirmarea primirii mesajului de tip FINISH */
if (p.type == FINISH) {
break;
}
}
printf("[SERVER] File transfer has ended.\n");
close(fd);
return 0;
}