-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathserver.cpp
449 lines (424 loc) · 15.5 KB
/
server.cpp
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
#include<iostream>
#include<WinSock2.h>
#include<time.h>
#include<fstream>
#include<iostream>
#include<windows.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
//初始化dll
WSADATA wsadata;
//声明服务器需要的套接字以及套接字需要绑定的地址
SOCKADDR_IN server_addr;
SOCKET server;
//声明路由器需要的套接字以及套接字需要绑定的地址
SOCKADDR_IN router_addr;;
//声明客户端的地址
SOCKADDR_IN client_addr;
char* sbuffer = new char[1000];
char* rbuffer = new char[1000];
char* message = new char[100000000];
unsigned long long int messagepointer;
//服务器地址的性质
int clen = sizeof(client_addr);
int rlen = sizeof(router_addr);
//常数设置
u_long blockmode = 0;
u_long unblockmode = 1;
const unsigned char MAX_DATA_LENGTH = 0xff;
const u_short SOURCEIP = 0x7f01;
const u_short DESIP = 0x7f01;
const u_short SOURCEPORT = 8888;//源端口是8888
const u_short DESPORT = 8887;//客户端端口号是8887
const unsigned char SYN = 0x1;//OVER=0,FIN=0,ACK=0,SYN=1
const unsigned char ACK = 0x2;//OVER=0,FIN=0,ACK=1,SYN=0
const unsigned char SYN_ACK = 0x3;//OVER=0,FIN=0,ACK=1,SYN=1
const unsigned char OVER = 0x8;//OVER=1,FIN=0,ACK=0,SYN=0
const unsigned char OVER_ACK = 0xA;//OVER=1,FIN=0,ACK=1,SYN=0
const unsigned char FIN = 0x10;//FIN=1,OVER=0,FIN=0,ACK=0,SYN=0
const unsigned char FIN_ACK = 0x12;//FIN=1,OVER=0,FIN=0,ACK=1,SYN=0
const unsigned char FINAL_CHECK=0x20;//FC=1.FIN=0,OVER=0,FIN=0,ACK=0,SYN=0
const double MAX_TIME = 0.2*CLOCKS_PER_SEC;
//数据头
struct Header {
u_short checksum; //16位校验和
u_short seq; //8位序列号,因为是停等,所以只有最低位实际上只有0和1两种状态
u_short ack; //8位ack号,因为是停等,所以只有最低位实际上只有0和1两种状态
u_short flag;//8位状态位 倒数第一位SYN,倒数第二位ACK,倒数第三位FIN,倒数第四位是结束位
u_short length;//8位长度位
u_short source_ip; //16位ip地址
u_short des_ip; //16位ip地址
u_short source_port; //16位源端口号
u_short des_port; //16位目的端口号
Header() {//构造函数
checksum = 0;
source_ip = SOURCEIP;
des_ip = DESIP;
source_port = SOURCEPORT;
des_port = DESPORT;
seq = 0;
ack = 0;
flag = 0;
length = 0;
}
};
//全局时钟设置
clock_t linkClock;
void printcharstar(char* s, int l) {
for (int i = 0; i < l; i++) {
cout << (int)s[i];
}
cout << endl;
}
void printheader(Header& h) {
cout << "checksum=" << h.checksum << endl;
cout << "se1=" << h.seq << endl;
cout << "ack=" << h.ack << endl;
cout << "flag=" << h.flag << endl;
cout << "length=" << h.length << endl;
cout << "sourceip=" << h.source_ip << endl;
cout << "desip=" << h.des_ip << endl;
cout << "source_port=" << h.source_port << endl;
cout << "des_port=" << h.des_port << endl;
}
//sizeof返回内存字节数 ushort是16位2字节,所以需要把size向上取整
u_short calcksum(u_short* mes, int size) {
int count = (size + 1) / 2;
u_short* buf = (u_short*)malloc(size + 1);
memset(buf, 0, size + 1);
memcpy(buf, mes, size);
u_long sum = 0;
buf += 1;
count -= 1;
while (count--) {
sum += *buf++;
if (sum & 0xffff0000) {
sum &= 0xffff;
sum++;
}
}
return ~(sum & 0xffff);
}
u_short vericksum(u_short* mes, int size) {
int count = (size + 1) / 2;
u_short* buf = (u_short*)malloc(size + 1);
memset(buf, 0, size + 1);
memcpy(buf, mes, size);
u_long sum = 0;
//buf += 2;
//count -= 2;
while (count--) {
sum += *buf++;
if (sum & 0xffff0000) {
sum &= 0xffff;
sum++;
}
}
return ~(sum & 0xffff);
}
void test();
void initialNeed();
int tryToConnect();
int receivemessage();
int endreceive();
int loadmessage();
int tryToDisconnect();
int main() {
initialNeed();
tryToConnect();
receivemessage();
loadmessage();
tryToDisconnect();
}
void initialNeed() {
WSAStartup(MAKEWORD(2, 2), &wsadata);
//指定服务端的性质
server_addr.sin_family = AF_INET;//使用IPV4
server_addr.sin_port = htons(8888);//server的端口号
server_addr.sin_addr.s_addr = htonl(2130706433);//主机127.0.0.1
//指定路由器的性质
router_addr.sin_family = AF_INET;//使用IPV4
router_addr.sin_port = htons(8886);//router的端口号
router_addr.sin_addr.s_addr = htonl(2130706433);//主机127.0.0.1
//指定一个客户端
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(8887);
client_addr.sin_addr.s_addr = htonl(2130706433);//主机127.0.0.1
//绑定服务端
server = socket(AF_INET, SOCK_DGRAM, 0);
bind(server, (SOCKADDR*)&server_addr, sizeof(server_addr));
//计算地址性质
int clen = sizeof(client_addr);
int rlen = sizeof(router_addr);
cout << "[PREPARE]初始化工作完成" << endl;
}
//检测你的初始化是否正确,并不提供功能型帮助
void test() {
while (true) {
int length = recvfrom(server, rbuffer, 1000, 0, (sockaddr*)&router_addr, &clen);
cout << length << " " << rbuffer << endl;
sbuffer[0] = 'A'; sbuffer[1] = 'C'; sbuffer[2] = 'K'; sbuffer[3] = '\0';
sendto(server, sbuffer, 1000, 0, (sockaddr*)&router_addr, rlen);
}
}
int tryToConnect() {
linkClock = clock();
Header header;//声明一个数据头
char* recvshbuffer = new char[sizeof(header)];//创建一个和数据头一样大的接收缓冲区
char* sendshbuffer = new char[sizeof(header)];//创建一个和数据头一样大的发送缓冲区
cout << "[0]正在等待连接...." << endl;
//等待第一次握手
while (true) {
//收到了第一次握手的申请
//我觉得他写的不对 返回值不太对
ioctlsocket(server, FIONBIO, &unblockmode);
while (recvfrom(server, recvshbuffer, sizeof(header), 0, (sockaddr*)&router_addr, &rlen)<=0) {
if (clock() - linkClock > 75 * CLOCKS_PER_SEC) {
cout << "[failed]连接超时,服务器自动断开" << endl;
return -1;
}
//cout << "....第一次握手信息接受失败...." << endl;
//return -1;
}
memcpy(&header, recvshbuffer, sizeof(header));//给数据头赋值
//如果是单纯的请求建立连接请求,并且校验和相加取反之后就是0
if (header.flag == SYN || vericksum((u_short*)(&header), sizeof(header)) == 0) {
cout << "[1]成功接受客户端请求,第一次握手建立成功...." << endl;
break;
}
else {
//cout << vericksum((u_short*)(&header), sizeof(header)) << endl;
cout << "[failed]第一次握手数据包损坏,正在等待重传..." << endl;
}
}
SECONDSHAKE:
//准备发送第二次握手的信息
header.source_port = SOURCEPORT;
header.des_port = DESPORT;
header.flag = SYN_ACK;
header.source_port = SOURCEPORT;
header.des_port = DESPORT;
header.ack = (header.seq + 1) % 2;
header.seq = 0;
header.length = 0;
header.checksum = calcksum((u_short*)(&header), sizeof(header));
//cout << vericksum((u_short*)&header, sizeof(header)) << endl;
memcpy(sendshbuffer, &header, sizeof(header));
if (sendto(server, sendshbuffer, sizeof(header), 0, (sockaddr*)&router_addr, rlen) == -1) {
cout << "[failed]第二次握手消息发送失败...." << endl;
return -1;
}
cout << "[2]第二次握手消息发送成功...." << endl;
clock_t start = clock();
if (clock() - linkClock > 75 * CLOCKS_PER_SEC) {
cout << "[failed]连接超时,服务器自动断开" << endl;
return -1;
}
//第二次握手消息的超时重传 重传时直接重传sendshbuffer里的内容就可以
//我觉得他写的不对 返回值不太对
while (recvfrom(server, recvshbuffer, sizeof(header), 0, (sockaddr*)&router_addr, &rlen) <= 0) {
if (clock() - linkClock > 75 * CLOCKS_PER_SEC) {
cout << "[failed]连接超时,服务器自动断开" << endl;
return -1;
}
if (clock() - start > MAX_TIME) {
if (sendto(server, sendshbuffer, sizeof(header), 0, (sockaddr*)&router_addr, rlen) == -1) {
cout << "[failed]第二次握手消息重新发送失败...." << endl;
return -1;
}
cout << "[2]第二次握手消息重新发送成功...." << endl;
start = clock();
}
}
memcpy(&header, recvshbuffer, sizeof(header));
if (header.flag == ACK && vericksum((u_short*)(&header), sizeof(header)) == 0) {
cout << "[3]成功接收第三次握手消息!可以开始接收数据..." << endl;
SEND4:
header.source_port = SOURCEPORT;
header.des_port = DESPORT;
header.flag = ACK;
header.source_port = SOURCEPORT;
header.des_port = DESPORT;
header.ack = (header.seq + 1) % 2;
header.seq = 0;
header.length = 0;
header.checksum = calcksum((u_short*)(&header), sizeof(header));
memcpy(sendshbuffer, &header, sizeof(header));
sendto(server, sendshbuffer, sizeof(header), 0, (sockaddr*)&router_addr, rlen);
cout << "[EVERYTHING_DONE]确认信息传输成功...." << endl;
}
else {
cout << "[failed]不是期待的数据包,正在重传并等待客户端等待重传" << endl;
if (clock() - linkClock > 75 * CLOCKS_PER_SEC) {
cout << "[failed]连接超时,服务器自动断开" << endl;
return -1;
}
goto SECONDSHAKE;
}
LAST:
cout << "[WAITING]正在等待接收数据...." << endl;
return 1;
}
int loadmessage() {
cout << "[STORE]文件将被保存为1.png" << endl;
string filename="1.png";
ofstream fout(filename.c_str(), ofstream::binary);
for (int i = 0; i < messagepointer; i++)
{
fout << message[i];
}
fout.close();
cout << "[FINISH]文件已成功下载到本地" << endl;
return 0;
}
int receivemessage() {
Header header;
char* recvbuffer = new char[sizeof(header) + MAX_DATA_LENGTH];
char* sendbuffer = new char[sizeof(header)];
WAITSEQ0:
//接受seq=0的数据
while (true) {
//此时可以设置为阻塞模式
ioctlsocket(server, FIONBIO, &unblockmode);
while (recvfrom(server, recvbuffer, sizeof(header) + MAX_DATA_LENGTH, 0, (sockaddr*)&router_addr, &rlen) <= 0) {
//cout << "接受失败...请检查原因" << endl;
//cout << WSAGetLastError() << endl;
}
memcpy(&header, recvbuffer, sizeof(header));
//cout << header.flag << endl;
if (header.flag == OVER) {
//传输结束,等待添加....
if (vericksum((u_short*)&header, sizeof(header)) == 0) { if (endreceive()) { return 1; }return 0; }
else { cout << "[ERROR]数据包出错,正在等待重传" << endl; goto WAITSEQ0; }
}
cout << header.seq << " " << vericksum((u_short*)recvbuffer, sizeof(header) + MAX_DATA_LENGTH) << endl;
//printheader(header);
//printcharstar(recvbuffer, sizeof(header) + MAX_DATA_LENGTH);
if (header.seq == 0 && vericksum((u_short*)recvbuffer, sizeof(header)+MAX_DATA_LENGTH) == 0) {
cout << "[0CHECKED]成功接收seq=0数据包" << endl;
memcpy(message + messagepointer, recvbuffer + sizeof(header), header.length);
messagepointer += header.length;
break;
}
else {
cout << "[ERROR]数据包错误,正在等待对方重新发送" << endl;
}
}
header.ack = 1;
header.seq = 0;
header.checksum = calcksum((u_short*)&header, sizeof(header));
memcpy(sendbuffer, &header, sizeof(header));
SENDACK1:
if (sendto(server, sendbuffer, sizeof(header), 0, (sockaddr*)&router_addr, rlen) == -1) {
cout << "[failed]ack1发送失败...." << endl;
return -1;
}
clock_t start = clock();
RECVSEQ1:
//设置为非阻塞模式
ioctlsocket(server, FIONBIO, &unblockmode);
while (recvfrom(server, recvbuffer, sizeof(header) + MAX_DATA_LENGTH, 0, (sockaddr*)&router_addr, &rlen) <= 0) {
if (clock() - start > MAX_TIME) {
if (sendto(server, sendbuffer, sizeof(header), 0, (sockaddr*)&router_addr, rlen) == -1) {
cout << "[failed]ack1发送失败...." << endl;
return -1;
}
start = clock();
cout << "[ERROR]ack1消息反馈超时....已重发...." << endl;
goto SENDACK1;
}
}
memcpy(&header, recvbuffer, sizeof(header));
if (header.flag == OVER) {
//传输结束,等待添加....
if (vericksum((u_short*)&header, sizeof(header) == 0)) { if (endreceive()) { return 1; }return 0; }
else { cout << "[ERROR]数据包出错,正在等待重传" << endl; goto WAITSEQ0; }
}
cout << header.seq << " " << vericksum((u_short*)recvbuffer, sizeof(header) + MAX_DATA_LENGTH) << endl;
if (header.seq == 1 && vericksum((u_short*)recvbuffer, sizeof(header)+MAX_DATA_LENGTH)==0) {
cout << "[1CHECKED]成功接受seq=1的数据包,正在解析..." << endl;
memcpy(message + messagepointer, recvbuffer + sizeof(header), header.length);
messagepointer += header.length;
}
else {
cout << "[ERROR]数据包损坏,正在等待重新传输" << endl;
goto RECVSEQ1;
}
header.ack = 0;
header.seq = 1;
header.checksum = calcksum((u_short*)&header, sizeof(header));
memcpy(sendbuffer, &header, sizeof(header));
sendto(server, sendbuffer, sizeof(header), 0, (sockaddr*)&router_addr, rlen);
goto WAITSEQ0;
}
int endreceive() {
Header header;
char* sendbuffer = new char[sizeof(header)];
header.flag = OVER_ACK;
header.checksum = calcksum((u_short*)&header, sizeof(header));
memcpy(sendbuffer, &header,sizeof(header));
if (sendto(server, sendbuffer, sizeof(header), 0, (sockaddr*)&router_addr, rlen) >= 0) return 1;
cout << "[FINISH]确认消息发送成功" << endl;
return 0;
}
int tryToDisconnect() {
Header header;
char* sendbuffer = new char[sizeof(header)];
char* recvbuffer = new char[sizeof(header)];
RECVWAVE1:
while(recvfrom(server,recvbuffer,sizeof(header),0,(sockaddr*)&router_addr,&rlen)<=0){}
memcpy(&header, recvbuffer, sizeof(header));
if (header.flag == FIN && vericksum((u_short*)&header, sizeof(header)) == 0) {
cout << "收到第一次挥手信息" << endl;
}
else {
cout << "第一次挥手消息接收失败" << endl;
goto RECVWAVE1;
}
SEND2:
header.seq = 0;
header.flag = ACK;
header.checksum = calcksum((u_short*)&header, sizeof(header));
memcpy(sendbuffer, &header, sizeof(header));
if (sendto(server, sendbuffer, sizeof(header), 0, (sockaddr*)&router_addr, rlen) == -1) {
cout << "第二次挥手消息发送失败..." << endl;
return -1;
}
Sleep(80);
SEND3:
header.seq = 1;
header.flag = FIN_ACK;
header.checksum = calcksum((u_short*)&header, sizeof(header));
memcpy(sendbuffer, &header, sizeof(header));
if (sendto(server, sendbuffer, sizeof(header), 0, (sockaddr*)&router_addr, rlen) == -1) {
cout << "第三次挥手消息发送失败..." << endl;
return -1;
}
clock_t start = clock();
ioctlsocket(server, FIONBIO, &unblockmode);
while (recvfrom(server, recvbuffer, sizeof(header), 0, (sockaddr*)&router_addr, &rlen) <= 0) {
if (clock() - start > MAX_TIME) {
cout << "第四次挥手消息接收延迟...准备重发二三次挥手" << endl;
ioctlsocket(server, FIONBIO, &blockmode);
goto SEND2;
}
}
SEND5:
memcpy(&header, recvbuffer, sizeof(header));
if (header.flag == ACK && vericksum((u_short*)&header, sizeof(header)) == 0) {
header.seq = 0;
header.flag = FINAL_CHECK;
header.checksum = calcksum((u_short*)&header, sizeof(header));
memcpy(sendbuffer, &header, sizeof(header));
sendto(server, sendbuffer, sizeof(header), 0, (sockaddr*)&router_addr, rlen);
cout << "成功发送确认报文" << endl;
}
start = clock();
while (recvfrom(server, recvbuffer, sizeof(header), 0, (sockaddr*)&router_addr, &rlen) <= 0) {
if (clock() - start > 10 * MAX_TIME) {
cout << "四次挥手结束,已经断开连接" << endl;
return 1;
}
}
goto SEND5;
}