-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.c
150 lines (117 loc) · 3.33 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
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include "consts.h"
/*Basic program input error handling.*/
int verify_input(int argc, char **argv)
{
if (argc != 3)
{
printf("Usage: %s <port> <fname>\n", argv[0]);
return -1;
}
if (strlen(argv[2]) > FNAME_LEN)
{
printf("File name should be less than %d characters.\n", FNAME_LEN);
printf("'%s' has %d\n", argv[2], (int)strlen(argv[2]));
return -1;
}
return EXIT_SUCCESS;
}
/*Connect UDP socket to localhost:port.*/
int open_clientfd(int port, struct sockaddr_in *addr)
{
int sockfd;
char *ip = "127.0.0.1";
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(addr, '\0', sizeof(*addr));
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
addr->sin_addr.s_addr = inet_addr(ip);
if ((connect(sockfd, (struct sockaddr *)addr, sizeof(*addr)) < 0))
{
perror("Client connect");
close(sockfd);
return -1;
}
return sockfd;
}
/* Print transfer speed in MB/s */
void print_transfer_speed(clock_t t)
{
double mb = MAX_BUFF * 0.000001; // Bytes --> MB
double time = ((double)t) / CLOCKS_PER_SEC; // in seconds
double speed = mb / time;
printf("\r");
fflush(stdout);
printf("Transfer speed %.2fMB/s", speed);
}
int main(int argc, char **argv)
{
if (verify_input(argc, argv) == -1)
exit(EXIT_FAILURE);
// Get file name
char fname[FNAME_LEN];
strncpy(fname, argv[2], FNAME_LEN - 1);
fname[FNAME_LEN] = '\0';
// Connect socket
int port = atoi(argv[1]);
struct sockaddr_in addr;
int sockfd = open_clientfd(port, &addr);
if (sockfd == -1)
exit(EXIT_FAILURE);
char buffer[MAX_BUFF] = {0};
FILE *fp;
fp = fopen(fname, "r");
if (fp != NULL)
{
// Check file size
fseek(fp, 0, SEEK_END);
size_t file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
clock_t t;
size_t MAX_DATA_SIZE = MAX_BUFF - FNAME_LEN;
char data[MAX_DATA_SIZE];
bzero(data, MAX_DATA_SIZE);
// while (fread(data, sizeof(char), MAX_DATA_SIZE, fp) > 0)
while (fread(data, 1, MAX_DATA_SIZE, fp) > 0)
{
/*
Packets
Structure : [[FILE_NAME_LENGTH] [FILE_NAME] [DATA] ]
Size (bytes): [[2] [32] [<= (MAX_BUFFER - 2 - 32)]]
Always use 3 bytes for the file and data lengths.
For example:
If FILE_NAME_LENGTH = 5, format it as 05\0
If FILE_NAME_LENGTH = 15, format it as 15\0
*/
// Format file name length
char fnamelen[3];
if (strlen(fname) > 9) {
snprintf(fnamelen, sizeof(fnamelen), "%ld", strlen(fname));
} else {
snprintf(fnamelen, sizeof(fnamelen), "0%ld", strlen(fname));
}
// Copy data to buffer
memmove(buffer, fnamelen, sizeof(fnamelen));
memmove(&buffer[strlen(fnamelen)], fname, strlen(fname));
memmove(&buffer[strlen(fnamelen)+strlen(fname)], data, strlen(data));
// Send data and time command execution
t = clock();
sendto(sockfd, buffer, MAX_BUFF, 0, (struct sockaddr *)&addr, sizeof(addr));
t = clock() - t;
print_transfer_speed(t);
bzero(data, MAX_DATA_SIZE);
bzero(buffer, MAX_BUFF);
}
}
fclose(fp);
close(sockfd);
return EXIT_SUCCESS;
}