主要分为两人大模块:
客户端:
1、进入时的功能开户、销户、登录、解锁
开户:输入身份证号、设置密码,如果开户成功,则服务器上保存一个账号信号(一个账号存一个文件,文件名建议是账号)。
销户:输入帐号、密码,服务器询问是否确认销户,如果确认则服务器删除帐号文件,并记录帐号。
登录:输入账号、密码,三次错误账号锁定。
解锁:输入账号、身份证号解锁。
2、登录成功:存钱、取钱、转账、查询、修改密码
存钱:输入存钱金额
取钱:输入取钱金额
转账:目标帐号和要转的金额
查询:不需要输入数据
修改密码:原密码和新密码
服务端:
开启服务各项功能的子进程,各子进程按照消息类型接收消息
识别功能:根据消息的类型识别客户端请求的功能。
头文件
帐号结构体
{
帐号
身份证号
密码
金额
}
消息结构体
{
消息类型
帐号结构体
...
}
环境:
Ubuntu16.04 LTS系统
VScode代码编辑器+VIM代码编辑器
客户端
bank.h
#ifndef BANK_H
#define BANK_H
#define MSG_KEY ftok("../..",1)
#define LOG_PATH "../log/log.txt"
#define ACC_PATH "../acc/"
#define BANK_PATH "../acc/.bank.data"
#define M_CREATE 1 // 开户
#define M_DESTROY 2 // 销户
#define M_LOGIN 3 // 登录
#define M_UNLOCK 4 // 解锁
#define M_SAVE 5 // 存钱
#define M_TAKE 6 // 取钱
#define M_TRANSF 7 // 转账
#define M_QUERY 8 // 查询
#define M_MODIFY 9 // 改密码
#define LOCK_CNT 3 // 密码错误次数 >= LOCK_CNT 帐号锁定
typedef struct//帐户信息结构体
{
char bank[11]; // 卡号
char card[19]; // 证件号
char name[20]; // 姓名
char passwd[7]; // 密码
float balance; // 金额
char lock; // 是否锁定
}Acc;
typedef struct//客户端到服务器端的结构体
{
long type; // 消息类型
Acc acc; // 帐户信息
pid_t pid; // 客户端进程号
}Msgctos;
typedef struct//服务器端到客户端的结构体
{
long type; // 消息类型
char str[255]; // 提示信息
}Msgstoc;
#endif//BANK_H
client.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <tools.h>
#include <msg_queue.h>
#include "client_logon.h"
void create(void)
{
ctos.type = M_CREATE;
put_msg("请输入姓名:");
get_str(ctos.acc.name,sizeof(ctos.acc.name));
put_msg("请输入证件号:");
get_str(ctos.acc.card,sizeof(ctos.acc.card));
put_msg("请输入密码:");
get_passwd(ctos.acc.passwd,sizeof(ctos.acc.passwd),true);
put_msg("请输入预存的金额:");
scanf("%f",&ctos.acc.balance);
send_msg(msgfd,&ctos,sizeof(ctos));
debug("进程%u向服务端发送开户请求!\n",ctos.pid);
recv_msg(msgfd,&stoc,sizeof(stoc));
debug("进程%ld从服务端接收开户结果!\n",stoc.type);
put_msg("%s\n",stoc.str);
}
void destroy(void)
{
ctos.type = M_DESTROY;
put_msg("请输入卡号:");
get_str(ctos.acc.bank,sizeof(ctos.acc.bank));
put_msg("请输入姓名:");
get_str(ctos.acc.name,sizeof(ctos.acc.name));
put_msg("请输入证件号:");
get_str(ctos.acc.card,sizeof(ctos.acc.card));
put_msg("请输入密码:");
get_passwd(ctos.acc.passwd,sizeof(ctos.acc.passwd),true);
send_msg(msgfd,&ctos,sizeof(ctos));
debug("进程%u向服务端发送开户请求!\n",ctos.pid);
recv_msg(msgfd,&stoc,sizeof(stoc));
debug("进程%ld从服务端接收开户结果!\n",stoc.type);
put_msg("%s\n",stoc.str);
}
void login(void)
{
ctos.type = M_LOGIN;
put_msg("请输入卡号:");
get_str(ctos.acc.bank,sizeof(ctos.acc.bank));
put_msg("请输入密码:");
get_passwd(ctos.acc.passwd,sizeof(ctos.acc.passwd),true);
send_msg(msgfd,&ctos,sizeof(ctos));
debug("进程%u向服务端发送开户请求!\n",ctos.pid);
recv_msg(msgfd,&stoc,sizeof(stoc));
debug("进程%ld从服务端接收开户结果!\n",stoc.type);
if(NULL != strstr(stoc.str,"success"))
{
sscanf(stoc.str,"result:success info:%s",ctos.acc.name);
logon();
}
else
put_msg("%s\n",stoc.str);
}
void unlock(void)
{
put_msg(__func__);
}
void menu_main(void)
{
put_msg("***欢迎使用指针银行交易系统***\n");
put_msg("1、开户 2、销户\n");
put_msg("3、登录 4、解锁\n");
put_msg("5、退出系统\n");
put_msg("---------------------\n");
put_msg("请输入指令:");
}
int main(int argc,const char* argv[])
{
msgfd = get_msg(MSG_KEY);
debug("获取消息队列描述符 msgfd = %d\n",msgfd);
ctos.pid = getpid();
stoc.type = getpid();
for(;;)
{
menu_main();
switch(get_cmd(