-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.c
executable file
·153 lines (134 loc) · 5.04 KB
/
client.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
//Client
#include "RDP.h"
int makeFile(char fileName[]){ //Function to make a new file with random name
char *kf = "kernel-file-";
srand(time(NULL));
int fileNumb = random() % 1000;
sprintf(fileName, "%s%d", kf, fileNumb);
if (access(fileName, F_OK) == 0){ //Checks if the file already exists
printf("access: File with filename %s already exists.\n", fileName);
return 0;
}else{
return 1;
}
}
void confPck(unsigned char ack, int srvID, int cliID, int fd, struct sockaddr_in srvAddr){ //Function to send ACK-packet back to server
struct rdpPacket ackPacket = makePacket(0x8, 0, ack, cliID, srvID, 0);
unsigned int size;
char *serialAck = serialize(&ackPacket, &size);
sendNcheck(fd, size, serialAck, srvAddr);
free(serialAck);
}
int main(int argc, char *argv[]){
int fd, wc, rc, clientID, srvID, port, curPload = 1;
float lossProb;
unsigned char seq, ack;
char buffer[BUFSIZE], fileName[16];
char *IP;
struct sockaddr_in srvAddr;
struct in_addr ipAddr;
socklen_t addrLength = sizeof(struct sockaddr_in);
FILE *fileCopy;
struct timeval timeout;
fd_set fds;
if(argc != 4){
fprintf(stderr, "Forventet bruk; '%s <IP> <portnummer> <tapssannsynlighet>'\n", argv[0]);
return EXIT_FAILURE;
}
IP = argv[1];
port = atoi(argv[2]);
lossProb = atof(argv[3]);
set_loss_probability(lossProb);
wc = inet_pton(AF_INET, IP, &ipAddr);
checkError(wc, "inet_pton");
if(!wc){
fprintf(stderr, "Invalid IP address: %s\n", IP);
return EXIT_FAILURE;
}
fd = socket(AF_INET, SOCK_DGRAM, 0);
checkError(fd, "socket");
srvAddr.sin_family = AF_INET;
srvAddr.sin_port = htons(port);
srvAddr.sin_addr = ipAddr;
//Send request to server
clientID = rdp_connect(fd, srvAddr); //Requests to connect to the server. The randomly chosen ID is returned
FD_ZERO(&fds);
FD_SET(fd,&fds);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
// Receive from server
rc = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
if(!rc){ //If server didn't respond in 1 sec, close connection
printf("Couldn't reach server.\n");
close(fd);
return EXIT_FAILURE;
}
if(FD_ISSET(fd, &fds)){
struct rdpPacket *reply = rdp_read(fd, buffer, srvAddr);
unsigned char curFlag = reply->flag;
int metDat = reply->metadata;
srvID = reply->senderid;
free(reply);
seq = 0;
ack = 0;
if(curFlag == 0x20){
if (metDat == 1111){
printf("Message from server: CLIENT ID %d NOT AVAILABLE\n", clientID);
}
else if (metDat == 2222){
printf("Message from server: LAST FILE TRANSFER HAS ALREADY BEGUN\n");
}
}
if(curFlag == 0x10){
printf("Server ID: %d\t Client ID: %d\n", srvID, clientID);
if(!makeFile(fileName)){
rdp_close(fd, clientID, srvID, seq, ack, srvAddr);
exit(EXIT_FAILURE);
}
fileCopy = fopen(fileName, "wb"); //Åpner en ny fil, som det skal kopieres til
if (fileCopy == NULL) { //Sjekker om åpning av den nye filen gikk bra
perror("fopen");
rdp_close(fd, clientID, srvID, seq, ack, srvAddr);
exit(EXIT_FAILURE);
}
}
while(curFlag != 0x20 && curPload){
struct rdpPacket *filePor = rdp_read(fd, buffer, srvAddr);
curPload = filePor->metadata;
if(curPload){
if(filePor->seqNumb == seq){
wc = fwrite(filePor->payload, sizeof(char), filePor->metadata, fileCopy);
ack = filePor->seqNumb;
if(seq == 0){
seq++;
}else{
seq = 0;
}
confPck(ack, srvID, clientID, fd, srvAddr); //Send ACK
curFlag = filePor->flag;
free(filePor->payload);
free(filePor);
}else{ //Server resent a packet, last ACK was probably lost
confPck(ack, srvID, clientID, fd, srvAddr); //Send a new ACK
curFlag = filePor->flag;
free(filePor->payload);
free(filePor);
}
}else{
ack = filePor->seqNumb;
if (seq == 0){
seq++;
}else{
seq = 0;
}
confPck(ack, srvID, clientID, fd, srvAddr); //Send ACK
rdp_close(fd, clientID, srvID, seq, ack, srvAddr); //Send disconnect-packet
fclose(fileCopy);
free(filePor);
printf("%s\n",fileName);
}
}
}
close(fd);
return EXIT_SUCCESS;
}