基于消息队列的银行系统-部分功能
基于消息队列的银行系统
基本需求:
1、分为客户端和服务端(c/s架构)
2、服务端与每个客户端通信、满足它们的各种请求
3、客户端主要功能:
1、开户 2、销户 3、解锁 4、退出
5、登录 6、查询 7、存钱 8、取款
9、转账 10、修改密码
4、推荐使用的技术:消息队列 + vfork + exec系统函数
Make file
CC=gcc
STD=-std=gnu99
FLAG=-Wall -Werror
BIN=open destory unlock login query save take transfer repass
TARGE=server client
TOOLS=msgq.c tools.call:$(BIN) $(TARGE)mv $(BIN) ./bin/./server%:%.c tools.c tools.h msgq.c msgq.h$(CC) $(STD) $(FLAG) $(TOOLS) $< -o $@clean:cd ./bin/ && rm -rf $(BIN) rm -rf *.o rm -rf *.h.gch rm -rf *~
基本工具类,给输入数据做一下限制
tools.h
#ifndef TOOLS_H
#define TOOLS_H
#include
#include
#include
#include
#include
#include
#include void clear_stdin(void);
char* get_str(char* str,size_t len);
char get_sex(void);
int get_cmd(int start,int end);
char* get_pw(char* passwd,bool is_show,size_t size);
void any_key(void);#endif//TOOLS_H
鉴于C语言下msg的函数使用参数过多给他封装一下
msgq.h
#ifndef MSGQ_H
#define MSGQ_H
#include int get_msg(const char *pathname, int proj_id);
int send_msg(int msgid,const void* msg,size_t len);
int recv_msg(int msgid,void* msg,size_t len,long type);
void del_msg(int msgid);#endif//MSGQ_H
msgq.c
#include
#include
#include
#include "msgq.h"int get_msg(const char *pathname, int proj_id)
{int msgid = msgget(ftok(pathname,proj_id),IPC_CREAT|0644);if(0 > msgid){perror("msgget");}return msgid;
}int send_msg(int msgid,const void* msg,size_t len)
{int ret = msgsnd(msgid,msg,len-sizeof(long),0);if(0 > ret){perror("msgsnd");}return ret;
}int recv_msg(int msgid,void* msg,size_t len,long type)
{int ret = msgrcv(msgid,msg,len,type,0);if(0 >= ret){perror("msgrcv");}return ret;
}void del_msg(int msgid)
{if(msgctl(msgid,IPC_RMID,NULL)){perror("msgctl");}
}
银行头文件,Account用户结构体,Msg消息结构体
bank.h
#ifndef BANK_H
#define BANK_H
#include
#include
#include
#include
#include #define MSGTY_OPEN (1)
#define MSGTY_DESTORY (2)
#define MSGTY_UNLOCK (3)
#define MSGTY_LOGIN (4)
#define MSGTY_QUERY (5)
#define MSGTY_SAVE (6)
#define MSGTY_TAKE (7)
#define MSGTY_TRANSFER (8)
#define MSGTY_REPASS (9)#define SUBP_CNT (9)
#define ACCOUNT_PATH "./account/"
#define ID_PATH "./account/.id.dat"typedef struct Account
{double balance;char id[20];char pass[7];char card[19];char islock;
}Account;typedef struct MSG_CTOS
{long type;Account acc;pid_t return_type;
}MSG_CTOS;typedef struct MSG_STOC
{long type;char info[256];
}MSG_STOC;#endif//BANK_H
服务端
server.c
#include
#include
#include
#include
#include "bank.h"pid_t subp[SUBP_CNT] = {};void sigint(int signum)
{for(int i=0; i<SUBP_CNT; i++){kill(subp[i],SIGINT);}exit(0);
}int main()
{// 绑定信号处理signal(SIGINT,sigint);// 启动子进程const char* paths[SUBP_CNT] = {"./bin/open","./bin/destory","./bin/unlock","./bin/login","./bin/query","./bin/save","./bin/take","./bin/transfer","./bin/repass",};for(int i=0; i<SUBP_CNT; i++){subp[i] = vfork();if(0 == subp[i]){execl(paths[i],paths[i],NULL);}}// 等待子进程结束while(-1 != wait(NULL));
}
客户端
server.c(简单写了几个功能、基本能够获取到数据,其余功能知识获取结构体的不同信息罢了:)
#include "msgq.h"
#include "bank.h"
#include "tools.h"int msgid = 0;
MSG_CTOS ctos = {};
MSG_STOC stoc = {};
static int lock = 0;void open_acc(void)
{msgid = get_msg(ACCOUNT_PATH,SUBP_CNT);ctos.return_type = getpid();ctos.type = MSGTY_OPEN;Account acc = {};printf("请输入姓名:");scanf("%s",acc.id);printf("请输入身份证:");scanf("%s",acc.card);printf("请输入密码:");scanf("%s",acc.pass);ctos.acc = acc;ctos.acc.islock = 0;ctos.acc.balance = 0;send_msg(msgid,&ctos,sizeof(MSG_CTOS));recv_msg(msgid,&stoc,sizeof(MSG_STOC),ctos.return_type);if(stoc.info != NULL){printf("帐号:%s,开户成功\n",stoc.info);}else{ printf("开户失败\n");}any_key();
}void login_menu(char* id);
void login(void)
{msgid = get_msg(ACCOUNT_PATH,SUBP_CNT);ctos.return_type = getpid();ctos.type = MSGTY_LOGIN;if(lock >= 3){printf("您已被锁定,请解锁\n");getchar();return;}Account acc = {};printf("请输入帐号:");scanf("%s",acc.id);printf("请输入密码:");scanf("%s",acc.pass);ctos.acc = acc;send_msg(msgid,&ctos,sizeof(MSG_CTOS));recv_msg(msgid,&stoc,sizeof(MSG_STOC),ctos.return_type);if(0 == strcmp(stoc.info,"Success pwdcorrect")){printf("%s,登陆成功\n",acc.id);getch();login_menu(acc.id);}else{ lock++; printf("帐号或密码错误\n");getch();}any_key();
}void destory(void)
{printf("%s",__func__);
}void unlock(void)
{printf("%s",__func__);
}void query(void)
{printf("%s",__func__);
}void save(void)
{printf("%s",__func__);
}void take(void)
{printf("%s",__func__);
}void transfer(void)
{printf("%s",__func__);
}void repass(void)
{printf("%s",__func__);
}int main_menu(void)
{system("clear");puts("***欢迎使用银行***");puts("1、开户 2、销户");puts("3、解锁 4、登录");puts("5、退卡");return get_cmd(1,5);
}int sub_menu(char* id)
{system("clear");char str[50] = {};sprintf(str,"***%s客户,您好!***",id);puts(str);puts("1、查询 2、存款");puts("3、取款 4、转账");puts("5、改密 6、退卡");return get_cmd(1,6);
}void login_menu(char* id)
{for(;;){switch(sub_menu(id)){case (1): query(); break;case (2): save(); break;case (3): take(); break;case (4): transfer(); break;case (5): repass(); break;case (6): exit(-1);}}
}int main()
{for(;;){switch(main_menu()){case (1): open_acc(); break;case (2): destory(); break;case (3): unlock(); break;case (4): login(); break;case (5): return 0;}}
}
创建账号
open.c 生成open
#include "msgq.h"
#include "tools.h"
#include "bank.h"int msgid = 0;
MSG_CTOS ctos = {};
MSG_STOC stoc = {};int open_acc(Account acc)
{printf("%s %lf\n",ctos.acc.card,ctos.acc.balance);char filename[40] = {"./data/"};sprintf(filename,"./data/%s.data",acc.id);acc.balance = 0;int fd = open(filename,O_CREAT|O_RDWR|O_EXCL,0644);if(fd == -1){perror("文件创建失败\n");return -1;}if(write(fd,&acc,sizeof(Account)) < 0){perror("write\n");return -1;}close(fd);printf("用户创建成功!\n");sprintf(stoc.info,"Y open success! %s.dat has been create",acc.id);return 0;
}int main(int argc,const char* argv[])
{printf("argv %s\n",argv[0]);msgid = get_msg(ACCOUNT_PATH,SUBP_CNT);for(;;){recv_msg(msgid,&ctos,sizeof(MSG_CTOS),MSGTY_OPEN);open_acc(ctos.acc);stoc.type = ctos.return_type;printf("%s\n",stoc.info);send_msg(msgid,&stoc,sizeof(MSG_STOC));}
}
再贴一个登录
login.c 生成 login
#include "msgq.h"
#include "bank.h"int msgid = 0;
MSG_CTOS ctos = {};
MSG_STOC stoc = {};int login(Account acc)
{char path[50] = "./data/";char ex[8] = ".data";sprintf(path,"%s%s%s",path,acc.id,ex);if(0 == access(path,F_OK)){Account buf = {};int fd = open(path,O_RDWR);if(0 != read(fd,&buf,sizeof(Account))){printf("acc id %s\n",acc.id);printf("acc pw %s\n",acc.pass);printf("buf id %s\n",buf.id);printf("buf pw %s\n",buf.pass);if((0 == strcmp(acc.id,buf.id)) && (0 == strcmp(acc.pass,buf.pass))){close(fd);printf("登陆成功\n");return 0;}else{printf("帐号或密码错误\n");close(fd);return -1;}}else{printf("读取信息失败\n");return -1;}}else{printf("此帐号不存在\n");return -1;}
}int main(int argc,const char* argv[])
{printf("argv %s\n",argv[0]);msgid = get_msg(ACCOUNT_PATH,SUBP_CNT);for(;;){recv_msg(msgid,&ctos,sizeof(MSG_CTOS),MSGTY_LOGIN);if(login(ctos.acc) == 0) sprintf(stoc.info,"Success pwdcorrect");stoc.type = ctos.return_type;send_msg(msgid,&stoc,sizeof(MSG_STOC));}
}
上述open和login上图效果,界面微丑:)
客户端创建用户 wangwei 123456
服务端反馈信息-创建成功!
在对应的bank/data下面生成对应文件
客户端下登录wangwei 123456
服务端登录成功!
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
