直接先上图:
项目需求:
主要分为两人大模块: 客户端 1、进入时的功能开户、销户、登录、解锁 开户:输入姓名、身份证号、设置密码,如果开户成功,则服务器上保存一个账号信号(一个账号存一个文件,文件名建议是账号)。 销户:输入帐号、密码,服务器询问是否确认销户,如果确认则服务器删除帐号文件,并记录帐号。(我没实现) 登录:输入账号、密码,三次错误账号锁定。 解锁:输入账号、身份证号解锁。 2、登录成功:存钱、取钱、转账、查询、修改密码 存钱:输入存钱金额 取钱:输入取钱金额 转账:目标帐号和要转的金额 查询:不需要输入数据 修改密码:原密码和新密码 服务器 如果识别功能:根据消息的类型识别客户端请求的功能。 开启服务各项功能的子进程 各进程按照消息类型接收消息
打开2个终端,一个编译所有文件
然后运行server(服务端)
另一个终端运行client(客户端)
切记不要关闭服务端。
接下来在客户端进行操作。
1、开户(客户端)
(服务端)会输出相关信息
2、销户
(客户端)
(服务端)
3、登录
(客户端)
(服务端)
登录后(子功能)
具体就不在列举了,下面提供部分源码,具体请移步码云,GitHub
server.c
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <signal.h> 4 #include <sys/ipc.h> 5 #include <sys/msg.h> 6 #include <sys/wait.h> 7 #include "struct.h" 8 #include "tools.h" 9 10 static int msgid_ctos; 11 static int msgid_stoc; 12 static pid_t sub_pid[9]; 13 14 void sigint(int sig) 15 { 16 msgctl(msgid_ctos,IPC_RMID,NULL); 17 msgctl(msgid_stoc,IPC_RMID,NULL); 18 19 int i; 20 for(i=0; i<9; i++) 21 { 22 kill(sub_pid[i],SIGKILL); 23 } 24 } 25 26 int main() 27 { 28 signal(SIGINT,sigint); 29 30 msgctl(msgid_ctos,IPC_RMID,NULL); 31 msgctl(msgid_stoc,IPC_RMID,NULL); 32 33 msgid_ctos = msgget(ftok(".",100),IPC_CREAT|IPC_EXCL|0644); 34 msgid_stoc = msgget(ftok(".",200),IPC_CREAT|IPC_EXCL|0644); 35 36 sub_pid[0] = vfork(); 37 if(0 == sub_pid[0]) 38 { 39 execl("login","login",NULL); 40 printf("登陆子进程创建成功...\n"); 41 } 42 43 sub_pid[1] = vfork(); 44 if(0 == sub_pid[1]) 45 { 46 execl("open","open",NULL); 47 printf("开户子进程创建成功...\n"); 48 } 49 sub_pid[2] = vfork(); 50 if(0 == sub_pid[2]) 51 { 52 execl("save","save",NULL); 53 } 54 55 sub_pid[3] = vfork(); 56 if(0 == sub_pid[3]) 57 { 58 execl("take","take",NULL); 59 } 60 61 sub_pid[4] = vfork(); 62 if(0 == sub_pid[4]) 63 { 64 execl("transf","transf",NULL); 65 } 66 67 sub_pid[5] = vfork(); 68 if(0 == sub_pid[5]) 69 { 70 execl("select","select",NULL); 71 } 72 73 //login open save take transf select change destory unlock 74 75 sub_pid[6] = vfork(); 76 if(0 == sub_pid[6]) 77 { 78 execl("change","change",NULL); 79 } 80 81 sub_pid[7] = vfork(); 82 if(0 == sub_pid[7]) 83 { 84 execl("destory","destory",NULL); 85 } 86 87 sub_pid[8] = vfork(); 88 if(0 == sub_pid[8]) 89 { 90 execl("unlock","unlock",NULL); 91 } 92 93 //pause(); 94 while(-1 != wait(NULL)); 95 }
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <signal.h> 4 #include <sys/ipc.h> 5 #include <sys/msg.h> 6 #include <sys/wait.h> 7 #include "struct.h" 8 #include "tools.h" 9 10 static int msgid_ctos; 11 static int msgid_stoc; 12 static pid_t sub_pid[9]; 13 14 void sigint(int sig) 15 { 16 msgctl(msgid_ctos,IPC_RMID,NULL); 17 msgctl(msgid_stoc,IPC_RMID,NULL); 18 19 int i; 20 for(i=0; i<9; i++) 21 { 22 kill(sub_pid[i],SIGKILL); 23 } 24 } 25 26 int main() 27 { 28 signal(SIGINT,sigint); 29 30 msgctl(msgid_ctos,IPC_RMID,NULL); 31 msgctl(msgid_stoc,IPC_RMID,NULL); 32 33 msgid_ctos = msgget(ftok(".",100),IPC_CREAT|IPC_EXCL|0644); 34 msgid_stoc = msgget(ftok(".",200),IPC_CREAT|IPC_EXCL|0644); 35 36 sub_pid[0] = vfork(); 37 if(0 == sub_pid[0]) 38 { 39 execl("login","login",NULL); 40 printf("登陆子进程创建成功...\n"); 41 } 42 43 sub_pid[1] = vfork(); 44 if(0 == sub_pid[1]) 45 { 46 execl("open","open",NULL); 47 printf("开户子进程创建成功...\n"); 48 } 49 sub_pid[2] = vfork(); 50 if(0 == sub_pid[2]) 51 { 52 execl("save","save",NULL); 53 } 54 55 sub_pid[3] = vfork(); 56 if(0 == sub_pid[3]) 57 { 58 execl("take","take",NULL); 59 } 60 61 sub_pid[4] = vfork(); 62 if(0 == sub_pid[4]) 63 { 64 execl("transf","transf",NULL); 65 } 66 67 sub_pid[5] = vfork(); 68 if(0 == sub_pid[5]) 69 { 70 execl("select","select",NULL); 71 } 72 73 //login open save take transf select change destory unlock 74 75 sub_pid[6] = vfork(); 76 if(0 == sub_pid[6]) 77 { 78 execl("change","change",NULL); 79 } 80 81 sub_pid[7] = vfork(); 82 if(0 == sub_pid[7]) 83 { 84 execl("destory","destory",NULL); 85 } 86 87 sub_pid[8] = vfork(); 88 if(0 == sub_pid[8]) 89 { 90 execl("unlock","unlock",NULL); 91 } 92 93 //pause(); 94 while(-1 != wait(NULL)); 95 }
client.c
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 #include <sys/types.h> 6 #include <sys/ipc.h> 7 #include <sys/msg.h> 8 #include <sys/stat.h> 9 #include <stdlib.h> 10 #include <fcntl.h> 11 #include "struct.h" 12 #include "tools.h" 13 //#include "msg_queue.c" 14 15 static long online = 0; 16 static int lock = 0; 17 18 int msgid_ctos; 19 int msgid_stoc; 20 21 int init(); 22 void open_acc(); 23 void destory(); 24 void login(); 25 void unlock(); 26 void user_menu(void); 27 void menu(void); 28 void save(); 29 void take(); 30 void transf(); 31 void select_money(); 32 void change_pw(); 33 34 int main() 35 { 36 init(); 37 menu(); 38 } 39 40 int init() 41 { 42 //msgctl(msgid_ctos,IPC_RMID,NULL); 43 // 创建消息队列 44 msgid_ctos = msgget(ftok(".",100),0); 45 if(0 > msgid_ctos) 46 { 47 perror("msgget"); 48 return -1; 49 } 50 msgid_stoc = msgget(ftok(".",200),0); 51 if(0 > msgid_stoc) 52 { 53 perror("msgget"); 54 return -1; 55 } 56 return 0; 57 } 58 59 void login()//0 60 { 61 if(lock >= 3) 62 { 63 printf("您已被锁定,请解锁\n"); 64 getchar(); 65 return; 66 } 67 Account acc = {}; 68 Msg msg = {110}; 69 printf("请输入帐号:"); 70 scanf("%ld",&acc.user); 71 getchar(); 72 printf("请输入密码:"); 73 get_str(acc.pw,20); 74 msg.acc = acc; 75 msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0); 76 77 Msg msg2 = {}; 78 // 接收消息 79 msgrcv(msgid_stoc,&msg2,sizeof(Msg),220,MSG_NOERROR); 80 81 if(acc.user == msg2.acc.user) 82 { 83 online = acc.user; 84 printf("%ld,登陆成功\n",online); 85 getch(); 86 user_menu(); 87 } 88 else 89 { 90 lock++; 91 printf("帐号或密码错误\n"); 92 getch(); 93 } 94 } 95 96 void open_acc()//1 97 { 98 99 Account acc = {}; 100 Msg msg = {111}; 101 printf("请输入姓名:"); 102 get_str(acc.name,20); 103 printf("请输入身份证:"); 104 get_str(acc.id,20); 105 printf("请输入密码:"); 106 get_str(acc.pw,20); 107 msg.acc = acc; 108 //printf("msg:%s\n",msg.acc.name); 109 msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0); 110 111 Msg msg2 = {}; 112 // 接收消息 113 msgrcv(msgid_stoc,&msg2,sizeof(Msg),221,MSG_NOERROR); 114 printf("msg2:%s,acc:%s\n",msg2.acc.name,acc.name); 115 if(strcmp(acc.name,msg2.acc.name) == 0) 116 { 117 //printf("%s\n",msg2.acc.name); 118 //printf("%s\n",msg2.acc.id); 119 printf("帐号:%ld,开户成功\n",msg2.acc.user); 120 } 121 else 122 { 123 printf("开户失败\n"); 124 } 125 getch(); 126 } 127 128 void save()//2 129 { 130 Account acc = {}; 131 Msg msg = {112}; 132 //printf("当前用户:%ld\n",online); 133 printf("请输入存款金额:"); 134 scanf("%lf",&acc.money); 135 getchar(); 136 acc.user = online; 137 msg.acc = acc; 138 msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0); 139 140 Msg msg2 = {}; 141 // 接收消息 142 msgrcv(msgid_stoc,&msg2,sizeof(Msg),222,MSG_NOERROR); 143 if(msg2.acc.user == online) 144 { 145 printf("存钱成功\n"); 146 } 147 else 148 { 149 printf("存钱失败\n"); 150 } 151 getch(); 152 } 153 154 void take()//3 155 { 156 Account acc = {}; 157 Msg msg = {113}; 158 printf("请输入取款金额:"); 159 scanf("%lf",&acc.money); 160 getchar(); 161 acc.user = online; 162 msg.acc = acc; 163 msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0); 164 165 Msg msg2 = {}; 166 // 接收消息 167 msgrcv(msgid_stoc,&msg2,sizeof(Msg),223,MSG_NOERROR); 168 if(msg2.acc.user == online) 169 { 170 printf("取钱成功\n"); 171 } 172 else if(msg2.acc.user == online + 2) 173 { 174 printf("余额不足,请充值\n"); 175 } 176 else 177 { 178 printf("取钱失败\n"); 179 } 180 getch(); 181 } 182 void transf()//4 183 { 184 Account acc = {}; 185 Msg msg = {114}; 186 printf("请输入转帐金额:"); 187 scanf("%lf",&acc.money); 188 getchar(); 189 acc.user = online; 190 msg.acc = acc; 191 msg.flag = 0; 192 msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0); 193 194 Msg msg2 = {}; 195 // 接收消息 196 msgrcv(msgid_stoc,&msg2,sizeof(Msg),224,MSG_NOERROR); 197 if(msg2.flag == 0) 198 { 199 printf("请输入要转帐的帐号:"); 200 scanf("%ld",&acc.user); 201 getchar(); 202 msg.acc = acc; 203 msg.flag = 1; 204 msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0); 205 206 // 接收消息 207 msgrcv(msgid_stoc,&msg2,sizeof(Msg),224,MSG_NOERROR); 208 209 if(msg2.flag == 2) 210 { 211 printf("转帐成功\n"); 212 } 213 else 214 { 215 printf("转帐失败\n"); 216 } 217 218 } 219 else 220 { 221 printf("余额不足,请充值\n"); 222 } 223 getch(); 224 } 225 void select_money()//5 226 { 227 Account acc = {}; 228 Msg msg = {115}; 229 acc.user = online; 230 msg.acc = acc; 231 msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0); 232 233 Msg msg2 = {}; 234 // 接收消息 235 msgrcv(msgid_stoc,&msg2,sizeof(Msg),225,MSG_NOERROR); 236 if(msg2.acc.user == online) 237 { 238 printf("余额:%.2lf\n",msg2.acc.money); 239 } 240 else 241 { 242 printf("查询失败\n"); 243 } 244 getch(); 245 } 246 void change_pw()//6 247 { 248 Account acc = {}; 249 Msg msg = {116}; 250 printf("请输入新密码:"); 251 get_str(acc.pw,20); 252 acc.user = online; 253 msg.acc = acc; 254 msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0); 255 256 Msg msg2 = {}; 257 // 接收消息 258 msgrcv(msgid_stoc,&msg2,sizeof(Msg),226,MSG_NOERROR); 259 if(msg2.acc.user == online) 260 { 261 printf("改密成功\n"); 262 } 263 else 264 { 265 printf("改密失败\n"); 266 } 267 getch(); 268 } 269 270 void destory()//7 271 { 272 Account acc = {}; 273 Msg msg = {117}; 274 printf("请输入销户帐号:"); 275 scanf("%ld",&acc.user); 276 getchar(); 277 printf("请输入姓名:"); 278 get_str(acc.name,20); 279 printf("请输入身份证:"); 280 get_str(acc.id,20); 281 msg.acc = acc; 282 msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0); 283 284 Msg msg2 = {}; 285 // 接收消息 286 msgrcv(msgid_stoc,&msg2,sizeof(Msg),227,MSG_NOERROR); 287 if(msg2.acc.user == 0) 288 { 289 printf("销户成功\n"); 290 } 291 else if(msg2.acc.user == 1) 292 { 293 printf("相关信息错误\n"); 294 } 295 else if(msg2.acc.user == 2) 296 { 297 printf("帐号不存在\n"); 298 } 299 getch(); 300 } 301 302 void unlock()//8 303 { 304 if(lock < 3) 305 { 306 printf("您没有被锁定,sorry\n"); 307 getchar(); 308 return; 309 } 310 Account acc = {}; 311 Msg msg = {118}; 312 printf("请输入帐号:"); 313 scanf("%ld",&acc.user); 314 getchar(); 315 printf("请输入姓名:"); 316 get_str(acc.name,20); 317 printf("请输入身份证:"); 318 get_str(acc.id,20); 319 msg.acc = acc; 320 msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0); 321 322 //printf("消息已发送到队列\n"); 323 324 Msg msg2 = {}; 325 // 接收消息 326 msgrcv(msgid_stoc,&msg2,sizeof(Msg),228,MSG_NOERROR); 327 328 //printf("已接收到队列的消息\n"); 329 printf("in:%ld,back:%ld\n",acc.user,msg2.acc.user); 330 331 if(acc.user == msg2.acc.user) 332 { 333 printf("%ld,解锁成功\n",acc.user); 334 lock = 0; 335 online = acc.user; 336 change_pw(); 337 } 338 else 339 { 340 printf("相关信息错误\n"); 341 getch(); 342 } 343 344 /* long user = 0; 345 char id[20] = {}; 346 char name[20] = {}; 347 printf("请输入要解锁的帐号:"); 348 scanf("%ld",&user); 349 getchar(); 350 351 char path[50] = "./data/"; 352 char ex[8] = ".dat"; 353 sprintf(path,"%s%ld%s",path,user,ex); 354 355 if(0 == access(path,F_OK)) 356 { 357 Account buf = {}; 358 int fd = open(path,O_RDWR); 359 if(0 != read(fd,&buf,sizeof(Account))) 360 { 361 char name[20] = {}; 362 char id[20] = {}; 363 printf("请输入此帐号开户姓名:"); 364 get_str(name,20); 365 printf("请输入此帐号开户身份证:"); 366 get_str(id,20); 367 368 if(strcmp(name,buf.name) == 0 && strcmp(id,buf.id) == 0) 369 { 370 online = user; 371 change_pw(); 372 lock = 0; 373 } 374 else 375 { 376 printf("输入信息有误\n"); 377 close(fd); 378 getch(); 379 } 380 } 381 else 382 { 383 printf("读取信息失败\n"); 384 getch(); 385 } 386 } 387 else 388 { 389 printf("此帐号不存在\n"); 390 getch(); 391 } 392 */ 393 } 394 395 void user_menu(void) 396 { 397 while(1) 398 { 399 system("clear"); 400 printf("--- 银行 ---\n"); 401 printf("1、 存钱\n"); 402 printf("2、 取钱\n"); 403 printf("3、 转帐\n"); 404 printf("4、 查询\n"); 405 printf("5、 改密\n"); 406 printf("0、 返回\n"); 407 switch(get_cmd(\'0\',\'5\')) 408 { 409 case \'1\':save(); break; 410 case \'2\':take(); break; 411 case \'3\':transf(); break; 412 case \'4\':select_money(); break; 413 case \'5\':change_pw();break; 414 case \'0\':return; 415 } 416 } 417 } 418 419 void menu(void) 420 { 421 while(1) 422 { 423 system("clear"); 424 printf("--- 银行 ---\n"); 425 printf("1、 开户\n"); 426 printf("2、 销户\n"); 427 printf("3、 登陆\n"); 428 printf("4、 解锁\n"); 429 printf("0、 退出\n"); 430 switch(get_cmd(\'0\',\'4\')) 431 { 432 case \'1\':open_acc(); break; 433 case \'2\':destory(); break; 434 case \'3\':login(); break; 435 case \'4\':unlock(); break; 436 case \'0\':return; 437 } 438 } 439 }