-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtcp_client.c
executable file
·196 lines (150 loc) · 4.21 KB
/
tcp_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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*******************************
tcp_client.c: the source file of the client in tcp transmission
********************************/
#include "headsock.h"
// file to be transmitted
#define FILENAME "myfile.txt"
// transmission function
float str_cli(FILE *fp, int sockfd, long *len);
// calculate the time interval between out and in
void tv_sub(struct timeval *out, struct timeval *in);
int main(int argc, char **argv) {
int sockfd, ret;
float ti, rt;
long len;
struct sockaddr_in ser_addr;
char ** pptr;
struct hostent *sh;
struct in_addr **addrs;
FILE *fp;
if (argc != 2) {
printf("Parameters do not match. Expected: <server_name/port>\n");
}
// get host's information
// sh is pointer to a struct
sh = gethostbyname(argv[1]);
if (sh == NULL) {
printf("error when gethostby name");
exit(0);
}
// print the remote host's information
printf("canonical name: %s\n", sh->h_name);
for (pptr=sh->h_aliases; *pptr != NULL; pptr++) {
printf("the aliases name is: %s\n", *pptr);
}
// checking the family address type
switch(sh->h_addrtype) {
case AF_INET:
printf("AF_INET\n");
break;
default:
printf("unknown addrtype\n");
break;
}
// take the address in sh (array of pointers)
addrs = (struct in_addr **)sh->h_addr_list;
// create the socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("error in socket");
exit(1);
}
// assign family
ser_addr.sin_family = AF_INET;
// assign port
ser_addr.sin_port = htons(MYTCP_PORT);
memcpy(&(ser_addr.sin_addr.s_addr), *addrs, sizeof(struct in_addr));
// write 8 zeroed bytes (unused field), the first 8 bits
bzero(&(ser_addr.sin_zero), 8);
// connect the socket with the host
ret = connect(sockfd, (struct sockaddr *)&ser_addr, sizeof(struct sockaddr));
if (ret != 0) {
printf ("connection failed\n");
close(sockfd);
exit(1);
}
if((fp = fopen ("myfile.txt","r+t")) == NULL) {
printf("File doesn't exit\n");
exit(0);
}
// perform the transmission and receiving
// ti = transfer time
ti = str_cli(fp, sockfd, &len);
// calculate the average transmission rate
rt = (len/(float) ti);
printf("Time(ms) : %.3f, Data sent(byte): %d\nData rate: %f (Kbytes/s)\n", ti, (int)len, rt);
close(sockfd);
fclose(fp);
exit(0);
}
float str_cli(FILE *fp, int sockfd, long *len) {
char *buf;
long lsize, ci;
struct ack_so ack;
struct pack_so sends;
int n, slen;
float time_inv = 0.0;
struct timeval sendt, recvt;
ci = 0;
fseek (fp , 0 , SEEK_END);
lsize = ftell (fp);
rewind (fp);
printf("The file length is %d bytes\n", (int) lsize);
printf("the packet length is %d bytes\n", DATALEN);
// allocate memory to contain the whole file.
buf = (char *) malloc (lsize);
if (buf == NULL) exit (2);
// copy the file into the buffer.
fread (buf, 1, lsize, fp);
/*** the whole file is loaded in the buffer. ***/
// append the end byte (null byte to terminate string)
buf[lsize] ='\0';
// get the current time (at start of transmission)
gettimeofday(&sendt, NULL);
while(ci<= lsize) {
if ((lsize+1-ci) <= DATALEN) {
slen = lsize+1-ci;
} else {
slen = DATALEN;
}
memcpy(sends.data, (buf+ci), slen);
// assign packet properties (len = length being sent, num = 0)
sends.len = slen;
sends.num = 0;
// send the data
n = send(sockfd, &sends, (sends.len + HEADLEN), 0);
if(n == -1) {
printf("send error!");
exit(1);
}
// wait for ack/nack from receiver
if ((n = recv(sockfd, &ack, 2, 0)) == -1) {
printf("Error when receiving ACK/NACK\n");
exit(1);
}
if(ack.num == ACK_CODE) {
// printf("Received ACK from Server\n");
ci += slen;
} else {
// printf("Received NACK from Server\n");
// continue without incrementing ci
continue;
}
}
// get current time (at the end of transmission)
gettimeofday(&recvt, NULL);
*len= ci;
// get the whole trans time
tv_sub(&recvt, &sendt);
//
time_inv += (recvt.tv_sec)*1000.0 + (recvt.tv_usec)/1000.0;
return(time_inv);
}
// method to calculate difference between out and in
void tv_sub(struct timeval *out, struct timeval *in) {
if ((out->tv_usec -= in->tv_usec) <0) {
--out ->tv_sec;
out ->tv_usec += 1000000;
}
out->tv_sec -= in->tv_sec;
}