-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbank_server.cpp
360 lines (260 loc) · 9.54 KB
/
bank_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
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <cstring>
#include <ctype.h>
#include <unistd.h> // write(),read(),lssek()...
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fstream> // 讀寫檔案
#include <pthread.h>
#include <ctime>
#include <time.h>
using namespace std;
constexpr unsigned int SERVER_PORT = 50544;
constexpr unsigned int buffer_size = 128;
constexpr unsigned int MSG_REPLY_LENGTH = 20;
constexpr unsigned int NUM_THREADS= 5;
pthread_mutex_t lock;
struct account{
string name;
string password;
int number;
int balance;
}info;
// error
// struct account detail;
// detail.password = "123456";
const char *pass = "123456";
// 紀錄服務項目
const char *service_buffer;
void *handle_connection(void *socket_arg);
void Login(void *socket);
void SaveMoney(void *socket);
void Withdraw(void *socket);
void Check_balance(void *socket);
void trans_detail(void);
int main(int argc, char *argv[])
{
char msg_buffer2[buffer_size];
void *ret; // receive the return value of thread
int new_socket[NUM_THREADS] ; // accept()return的值
pthread_t new_thread[NUM_THREADS];
int i = 0,num = 0;
// create server's socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
cerr << "open socket error" << endl;
return 1;
}
// 要再查setsockopt
int optval = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int));
struct sockaddr_in server_info, client_info;
bzero((char *) &server_info, sizeof(server_info));
server_info.sin_family = AF_INET; // 使用IPv4
server_info.sin_addr.s_addr = INADDR_ANY;
server_info.sin_port = htons(SERVER_PORT); // 設定port
// 把server的port和ID等資訊綁在socket
if (bind(sockfd, (struct sockaddr *) &server_info, sizeof(server_info)) < 0)
{
std::cerr << "bind error" << std::endl;
return 2;
}
// 計算接收client端的struct容器大小
socklen_t client_info_size = sizeof(client_info);
while(1)
{
// sock(監聽sockfd這個socket , 一次最多5人連到server)
if( listen(sockfd, 5) == -1 )
{
cerr <<"Can Not Listening"<< endl;
return 3;
};
// accept(): 會接收client的連線資訊
// 且 return 一個socket number, 之後就以這socket跟client通訊
new_socket[i] = accept(sockfd, (struct sockaddr *) &client_info, &client_info_size) ;
if(new_socket[i]<0)
{
cerr << "accept() is failed!" <<endl;
return 4;
}
cout << "server: got connection from = "
<< inet_ntoa( client_info.sin_addr)
<< " and port = " << ntohs( client_info.sin_port) << endl;
int status = pthread_create(&new_thread[num], NULL, handle_connection, &new_socket[i]);
if(status!= 0 )
{
cerr << " pthread_create() is failed ! " << endl;
return 5;
}
i++;
num++;
}
cout<<"Exit System"<<endl;
// close(new_socket[i]);
close(sockfd);
return 0;
}
//===============處理thread===================
void *handle_connection(void *socket_arg)
{
// Receive the identifier of client's socket
int client_socket = *(int *)socket_arg;
printf("It is from pthread ID - %1lu\n",pthread_self());
// 通知client連線成功
char reply[] = "You are connected!";
unsigned long int size = sizeof(reply)/sizeof(reply[0]);
write( client_socket ,reply,size);
char send_buffer[buffer_size];
char receive_buffer[buffer_size];
receive_buffer[buffer_size] = {0};
send_buffer[buffer_size] = {0};
// Got the request
while(1)
{
memset(receive_buffer,0,buffer_size);
cout << endl;
cout << "============ waiting next request ==============" << endl;
if (read(client_socket, &receive_buffer[0] , buffer_size )< 0)
{
cerr << "read from socket error" << endl;
return NULL ;
}
service_buffer = &receive_buffer[0];
cout << "Got the message :" << receive_buffer << endl;
// strcmp():字串相等 回傳0
if(strcmp(receive_buffer,"EXIT")!=0){
if(strcmp(receive_buffer,"LOGIN")==0)
Login(&client_socket);
else if(strcmp(receive_buffer,"SAVE")==0)
SaveMoney(&client_socket);
else if(strcmp(receive_buffer,"WITHDRAW")==0)
Withdraw(&client_socket);
else if(strcmp(receive_buffer,"BALANCE")==0)
Check_balance(&client_socket);
}
else{
cout << "Client will end the transaction!" <<endl;
break;
}
}
return NULL;
}
// ===============登入===============
void Login(void *socket)
{
int socket_id = *(int *)socket ;
string send_buffer(buffer_size,0);
string ret_buffer(buffer_size,0);
string receive_buffer(buffer_size,0);
cout << "------ Logining ------" << endl;
if ((read(socket_id ,&receive_buffer[0],buffer_size-1) < 0))
{
cerr << "The function read1() from client's message is failed!" <<endl;
return;
}
if(strcmp(receive_buffer.c_str(),pass)==0) send_buffer = "Login Succeed! ";
else send_buffer = "Login Failed! Please try again!";
write(socket_id ,send_buffer.c_str(), strlen(send_buffer.c_str()));
}
// ===============存款===============
void SaveMoney(void *socket)
{
int socket_id = *(int *)socket ;
string receive_buffer(buffer_size,0);
string send_buffer(buffer_size,0);
string ret_buffer(buffer_size,0);
pthread_mutex_lock(&lock);
cout << "------ Saving ------" << endl;
if ((read(socket_id ,&receive_buffer[0],buffer_size-1) < 0))
{
cerr << "The function read() from client's message is failed!" <<endl;
return;
}
cout << "Client wants to save $" << receive_buffer <<endl;
// string -> int ( using atoi() )
info.number = stoi(receive_buffer);
// Add to the balance
info.balance += info.number;
// int to string
ret_buffer = to_string(info.balance);
cout<<" The balance in Client's account is $" <<ret_buffer <<endl;
send_buffer = "The balance in your account is $";
send_buffer += ret_buffer;
write(socket_id ,send_buffer.c_str(), strlen(send_buffer.c_str()));
pthread_mutex_unlock(&lock);
}
// ==============提款===============
void Withdraw(void *socket)
{
int socket_id = *(int *)socket ;
string receive_buffer(buffer_size,0);
string send_buffer(buffer_size,0);
string ret_buffer(buffer_size,0);
pthread_mutex_lock(&lock);
cout << "------Withdrawing ------" << endl;
if ( (read(socket_id ,&receive_buffer[0],buffer_size-1 ) < 0))
{
cerr <<"The function read() from client's message is failed!" <<endl;
return ;
}
cout << "Client wants to withdraw $" << receive_buffer <<endl;
// convert string to int : By atoi()
info.number = stoi(receive_buffer);
// Subtract with the balance
info.balance -= info.number;
// int to string
ret_buffer = to_string(info.balance);
cout<<" The balance in Client's account is $" <<ret_buffer <<endl;
send_buffer = "The balance in your account is $";
send_buffer += ret_buffer;
write(socket_id ,send_buffer.c_str(), strlen(send_buffer.c_str()));
pthread_mutex_unlock(&lock);
}
//==============產生交易明細===============
void trans_detail(void)
{
ofstream fptr;
fptr.open("/home/ubuntupi/Desktop/transaction.html");
time_t curr_time;
curr_time = time(NULL);
char *time = ctime(&curr_time);
// 交易序號
srand( curr_time);
int id = rand();
fptr << " <!DOCTYPE html> "
<< "<table border=\"1\" cellpadding=\"1\" cellspacing=\"1\" style=\"width:600px\"><tbody>"
<< "<tr><td colspan=\"2\" style=\"text-align:center\"><span style=\"font-size:16px\">Bank Transcation Detail</span></td></tr>"
<< "<tr><td>交易時間</td><td>" << time << "</td></tr>"
<< "<tr><td>交易序號</td><td>" << id << "</td></tr>"
<< "<tr><td>服務項目</td><td>" << service_buffer << "</td></tr>"
<< "<tr><td>交易金額</td><td>" << info.number << "</td></tr>"
<< "<tr><td>帳戶餘額</td><td>" << info.balance << "</td></tbody></table>";
}
//==============查詢餘額===============
void Check_balance(void *socket)
{
int socket_id = *(int *)socket ;
string receive_buffer(buffer_size,0);
string send_buffer(buffer_size,0);
string ret_buffer(buffer_size,0);
pthread_mutex_lock(&lock);
cout << "------ Checking ------" << endl;
// int to string
ret_buffer = to_string(info.balance);
cout<<" The balance in Client's account is $" <<ret_buffer <<endl;
send_buffer = "The balance in your account is $";
send_buffer += ret_buffer;
write(socket_id ,send_buffer.c_str(), strlen(send_buffer.c_str()));
if ( (read(socket_id ,&receive_buffer[0],buffer_size-1 ) < 0))
{
cerr <<"The function read() from client's message is failed!" <<endl;
return ;
}
if(receive_buffer=="Y") trans_detail();
pthread_mutex_unlock(&lock);
}