Linux下使用消息队实现 ATM 自动取款机功能
要求功能:
(1)创建账户(2)存款(3)取款(4)查询(5)转账(6)退出(7)销户
用到的知识点:
文件操作--创建账户的时候要把用户名,密码,余额,银行卡号。。。。(每个银行卡号单独存放一个文件)
创建父子进程
进程通信----消息队列
模块化编程
项目分析:
1、实现功能用到进程间通信
1)通信要求两个进程实现两个进程分别完成什么任务??站在用户的角度去考虑这个问题:例如:你去银行办卡的场景
你:我要办卡
银行职员:请出示你的相关信息
你:交出身份证 银行职员:开始一系列的操作(录入信息,开账户等),紧接着要求你输入密码
你:输入密码
银行职员:请确认密码
你:再次输入
银行职员:系统会自动给你分配一个卡号
银行职员:银行卡余额不能为空,请存款
你:交出100元
银行职员:拿走你的钱,在你的账户输入100
............
............
从这个角度来讲你和银行职员就是两个不同的进程,你们分别的任务有:银行职员根据你的提示信息为你办卡、存款、取款、查询、转账、退出、销户操作,而你要做的就是给出相应的操作提示
2)进程间通信的选取
规定使用消息队列
整体思路
该项目主要分为客户端和服务器两大模块,客户端只用来处理客户的操作,并将数据发送给服务器,并且客户端不能直接访问存储的数据,所有数据由服务器访问并修改,并通过消息队列发送给客户端。服务器通过创建子程序,每个子程序调用不同的可执行文件来实现银行终端的功能。
模块分析
common.h头文件
包含了整个项目所需的头文件和数据类型
- C2SKEY和S2CKEY:客户端和服务器端消息队列创建时的键值
- enum opt {OPEN = 1, DEP, DISDEP, CHECK, TRANS, DELAC, QUIT};//办卡 存款 取款 查询 转账 销户 退出,定义了枚举菜单,消息队列通信时的消息类型
- 定义了传递消息的数据结构:
- DATA:账号信息的结构体 账号 户主 余额 密码 转账账户
- C2SMSG:客户端到服务器的消息格式 data结构体和 tyoe消息类型
- S2CMSG:服务器到客户端的响应消息格式 type消息类型, 账号 余额 户主
serve.c 服务器
主进程通过 for 循环来循环调用 fork 函数创建子进程,每个子进程独立处理一项功能,每个子进程通过消息队列和客户端进行通信,并使用消息改造函数改造二号信号,当服务器收到二号信号时,将会杀死所有子程序,并且删除消息队列,退出服务器
main()函数
- 创建消息队列
- 根据 infor 数组,通过fork函数创建子进程,infor 数组包含可执行文件的路径和文件名
- 每个子进程调用execl函数来执行相应的可执行文件,实现相应功能
- 主进程等待二号信号来调用stop()函数
stop()函数
- 收到二号信号时被调用
- 遍历杀死每个子进程
- 删除消息队列
- 退出服务器
client.c 客户端
创建消息队列和服务器进行通信,通过菜单界面提示用户相应的功能并调用相应的功能函数,功能函数会根据用户的输入发送消息给服务器来获取相应的数据,但客户端本身并不能操作数据,客户端接收服务器的消息结果并显示给用户,通过主循环来实现客户端的循环运行。
main()函数 循环调用,整个客户端框架
- 访问服务器消息队列
- 循环调用 menu() 函数来显示菜单并获取选择
- 根据选择调用不同的功能函数
menu()函数 菜单
- 通过枚举变量打印菜单
- 获取用户选择并返回相应编号
- 调用 glob() 函数来查询指定目录下的所有账号文件,每次菜单被调用的时候就刷新一次
CREATACCOUNT() 函数 创建银行卡号
- 获取用户输入的账号信息并判断是否合法
- 构造访问服务器的消息结构体
- 通过消息队列将创建的账号信息发送到服务器
- 接收并处理服务器返回的结果
- 完成办卡功能
dep() 函数 存款 disdep() 函数 取款 check() 函数 查询 delac() 函数 销户 trans() 函数 转账
这些函数思路基本一致,所以整体列出
- 获取用户输入的账号
- 使用字符串拼接函数拼接成账号文件名,通过遍历来与 glob() 函数获取的文件名比较
- 查询到账号文件向服务器发送请求,服务器返回账号信息,否则打印错误信息并退出功能函数
- 根据账号信息来确定用户操作是否合法,如果非法则退出功能函数,并向服务器发送错误信息,使服务器的相应功能重置为初始状态方便下次访问,如果用户操作合法,向服务器发送操作后的账号信息,服务器接收并作出相应处理
- 接收服务器的返回结果并打印
clear() 和 clears() 清理函数
- 清理输入缓冲区和屏幕
open.c 服务器办卡功能
通过消息队列接收客户端的账号信息,通过字符串拼接将银行卡号和 .txt 拼接起来作为账户i信息文件名,并创建相应的账号文件来保存信息
main() 函数
- 创建消息队列
- 循环接收客户端的办卡请求
- 调用 CREATID() 生成新账号
- 调用 save_info() 来保存文件
- 构造响应消息,发送给客户端
CREATID() 函数 生成银行卡号
- 打开账号ID记录文件id.txt
- 读取当前最大账号ID
- 递增生成新账号
- 写入新ID,返回给主函数
save_info()函数
- 根据账号创建对应数据文件
- 将办卡信息写入该文件
dep.c 服务器存款功能 disdep.c 服务器取款功能 check.c 服务器查询功能 trans.c 服务器转账功能 delac.c 服务器销户功能
这些模块功能基本一致,所以整体列出
- 创建消息队列
- 接收客户端所发送的账户文件名
- 向客户端发送账户的具体信息,如银行卡号,余额,户主等等
- 再次接收客户端所发送的信息,并进行判断,让如果是错误信息则初始化该模块功能,方便下次调用,如果是正确信息则继续服务器该功能,继续向下执行,最后返回处理结果给客户端
代码展示
common.h
//所有.c要用到的头文件
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <glob.h>
//传递信息要用到的结构类型
#define C2SKEY 0X12345//客户端向服务器发送
#define S2CKEY 0X54321//服务器向客户端发送
//开户 存款 取款 查询 转账 销户 退出
enum opt {OPEN = 1, DEP, DISDEP, CHECK, TRANS, DELAC, QUIT};
struct DATA{
int id;//账号
char name[20];//姓名
char passwd[20];//密码
float money;//余额
int o_id;//收款方账号(只有转账用)
pid_t pid;//客户端的pid号
};
struct C2SMSG{
long type;//客户端向服务器发送消息的类型
struct DATA data;//消息内容
};
struct S2CMSG{
long type;//服务器回复客户端的消息类型
int id;//账号(开户使用)
float money;//余额(和钱有关的操作都要使用)
char info[32];//提示信息
};
client.c
#include <common.h>
//函数声明
void clears();
void clear();
enum opt menu();
void CREATACCOUNT();
void dep();
void disdep();
void check();
void trans();
void delac();
//全局变量
int s2cmsgid, c2smsgid;
struct C2SMSG W_buf;
struct S2CMSG R_buf;
glob_t file = {0};
int len = 0;
int main(){
int num = 0;
printf("客户端启动\n");
//访问消息队列
s2cmsgid = msgget(S2CKEY, IPC_CREAT | 0644);
if(s2cmsgid == -1){
perror("msgget err");
return -1;
}
c2smsgid = msgget(C2SKEY, IPC_CREAT | 0644);
if(c2smsgid == -1){
perror("msgget err");
}
clears();
while(1){
num = menu();
switch(num){
case OPEN: CREATACCOUNT();
break;
case DEP: dep();
break;
case DISDEP: disdep();
break;
case CHECK: check();
break;
case TRANS: trans();
break;
case DELAC: delac();
break;
case QUIT: return 0;
break;
}
}
}
//菜单
enum opt menu(){
enum opt num;
glob("/home/yyy/linux/银行项目/src/*.txt", 0, NULL, &file); //获取所有账号文件
len = strlen("/home/yyy/linux/银行项目/src/");
// printf("%d\n", len);
while(1){
printf("%d.开户\n", OPEN);
printf("%d.存款\n", DEP);
printf("%d.取款\n", DISDEP);
printf("%d.查询\n", CHECK);
printf("%d.转账\n", TRANS);
printf("%d.销户\n", DELAC);
printf("%d.退出\n", QUIT);
printf("请选择功能\n");
scanf("%d",(int *)&num);
clear();
if(num > QUIT || num < OPEN){
clears();
printf("非法输入,请重新输入\n");
}
else{
clears();
return num;
}
}
}
//开户
void CREATACCOUNT(void){
char ch = 0;
char pws1[32] = {0}, pws2[32] = {0};
printf("请输入姓名\n");
scanf("%s", W_buf.data.name);
clear();
clears();
while(1){
printf("请输入密码\n");
scanf("%s", pws1);
clear();
clears();
printf("请再次输入密码\n");
scanf("%s", pws2);
clear();
if(!strcmp(pws1, pws2)){
clears();
strcpy(W_buf.data.passwd, pws1);
printf("密码创建成功\n");
break;
}
else{
clears();
printf("密码输入不一致,请重新输入\n");
}
}
printf("请输入金额\n");
scanf("%f",&W_buf.data.money);
clear();
clears();
W_buf.data.pid = getpid();
W_buf.type = OPEN;
if(msgsnd(c2smsgid, &W_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
if(msgrcv(s2cmsgid,&R_buf, sizeof(struct S2CMSG) - sizeof(long), getpid(), 0) == -1){
perror("msgrcv err");
return;
}
if(!strcmp(R_buf.info, "开户失败")){
printf("%s\n", R_buf.info);
}
else{
printf("%s\n", R_buf.info);
printf("账号 : %d\n", R_buf.id);
printf("户主 : %s\n", W_buf.data.name);
printf("余额 : %f\n", R_buf.money);
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
}
}
//存款
void dep(){
int id = 0;
char passwd[20] = {0};
char filename[64] = {0};
char ch = 0;
//{}int fd = 0;
int num = 0;
float money = 0;
struct C2SMSG r_buf;
struct S2CMSG w_buf;
printf("请输入银行卡号\n");
scanf("%d", &id);
clear();
sprintf(filename, "%d.txt", id);
//查找该账号是否存在
for(num = 0; num < file.gl_pathc; num ++){
if(! strcmp(file.gl_pathv[num] + len, filename)){
break;
}
}
if(num == file.gl_pathc){
printf("银行卡号不存在,已退出\n");
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return ;
}
// strcpy(r_buf.data.name, file.gl_pathv[num]);
r_buf.data.id = id;
r_buf.data.pid = getpid();
r_buf.type = DEP;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
if(msgrcv(s2cmsgid,&r_buf, sizeof(struct C2SMSG) - sizeof(long), getpid(), 0) == -1){
perror("msgrcv err");
return;
}
// read(fd,&r_buf, sizeof(struct C2SMSG));
// if(r_buf.data.id == id){
num = 0;
while(1){
printf("请输入密码\n");
scanf("%s", passwd);
clear();
if(! (id = strcmp(r_buf.data.passwd, passwd))){
clears();
printf("密码正确\n");
break;
}
else{
clears();
printf("密码或账号错误\n");
num ++;
}
if(num == 3){
clears();
printf("密码错误3次,已退出\n");
printf("按任意键继续\n");
W_buf.type = DEP;
W_buf.data.id = -1;
if(msgsnd(c2smsgid, &W_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
}
num = 0;
while(1){
printf("请输入存款金额\n");
scanf("%f", &money);
clear();
if(money == 0 && num < 4){
clears();
printf("存款金额错误,请重新输入\n");
num ++;
}
else{
clears();
r_buf.data.money = money + r_buf.data.money;
// printf("%f\n", r_buf.data.money);
break;
}
if(num == 3){
clears();
printf("金额错误3次,已退出\n");
printf("按任意键继续\n");
W_buf.data.id = -1;
W_buf.type = DEP;
if(msgsnd(c2smsgid, &W_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
}
// clear();
// clears();
r_buf.data.pid = getpid();
r_buf.type = DEP;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
if(msgrcv(s2cmsgid,&w_buf, sizeof(struct S2CMSG) - sizeof(long), getpid(), 0) == -1){
perror("msgrcv err");
return;
}
if(!strcmp(w_buf.info, "存款失败")){
printf("%s\n", w_buf.info);
}
else{
printf("%s\n", w_buf.info);
printf("账号 : %d\n", w_buf.id);
printf("户主 : %s\n", r_buf.data.name);
printf("余额 : %f\n", w_buf.money);
// while(1){
// if(getchar()){
// clears();
// break;
// }
// }
}
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
// }
}
//取款
void disdep(){
int id = 0;
char passwd[20] = {0};
char filename[64] = {0};
char ch = 0;
//int fd = 0;
int num = 0;
float money = 0;
struct C2SMSG r_buf;
struct S2CMSG w_buf;
printf("请输入银行卡号\n");
scanf("%d", &id);
clear();
sprintf(filename, "%d.txt", id);
//查找该账号是否存在
for(num = 0; num < file.gl_pathc; num ++){
if(! strcmp(file.gl_pathv[num] + len, filename)){
break;
}
}
if(num == file.gl_pathc){
printf("银行卡号不存在,已退出\n");
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return ;
}
// strcpy(r_buf.data.name, file.gl_pathv[num]);
r_buf.data.id = id;
r_buf.data.pid = getpid();
r_buf.type = DISDEP;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
if(msgrcv(s2cmsgid,&r_buf, sizeof(struct C2SMSG) - sizeof(long), getpid(), 0) == -1){
perror("msgrcv err");
return;
}
// if(r_buf.data.id == id){
clears();
num =0;
while(1){
printf("请输入密码\n");
scanf("%s", passwd);
clear();
if(! (id = strcmp(r_buf.data.passwd, passwd))){
clears();
printf("密码正确\n");
break;
}
else{
clears();
printf("密码或账号错误\n");
num ++;
}
if(num == 3){
clears();
printf("密码错误3次,已退出\n");
printf("按任意键继续\n");
r_buf.type = DISDEP;
r_buf.data.id = -1;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
}
num = 0;
while(1){
printf("卡号:%d\n", r_buf.data.id);
printf("余额:%f\n", r_buf.data.money);
printf("请输入取款金额\n");
scanf("%f", &money);
clear();
if((money == 0 && num < 4) || (money < 0 && num < 4) || (money > r_buf.data.money && num < 4)){
clears();
printf("取款金额错误,请重新输入\n");
num ++;
}
else{
clears();
r_buf.data.money = r_buf.data.money - money;
// printf("%f\n", r_buf.data.money);
break;
}
if(num == 3){
clears();
printf("金额错误3次,已退出\n");
W_buf.type = DISDEP;
W_buf.data.id = -1;
if(msgsnd(c2smsgid, &W_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
}
// clear();
// clears();
r_buf.data.pid = getpid();
r_buf.type = DISDEP;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
if(msgrcv(s2cmsgid,&w_buf, sizeof(struct S2CMSG) - sizeof(long), getpid(), 0) == -1){
perror("msgrcv err");
return;
}
if(!strcmp(w_buf.info, "取款失败")){
printf("%s\n", w_buf.info);
}
else{
printf("%s\n", w_buf.info);
printf("账号 : %d\n", w_buf.id);
printf("户主 : %s\n", r_buf.data.name);
printf("余额 : %f\n", w_buf.money);
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
// }
}
//查询
//存款
void check(){
int id = 0;
char passwd[20] = {0};
char filename[64] = {0};
char ch = 0;
//int fd = 0;
int num = 0;
//float money = 0;
struct C2SMSG r_buf;
struct S2CMSG w_buf;
//复制
//查找该账号是否存在
printf("请输入银行卡号\n");
scanf("%d", &id);
clear();
sprintf(filename, "%d.txt", id);
//查找该账号是否存在
for(num = 0; num < file.gl_pathc; num ++){
if(! strcmp(file.gl_pathv[num] + len, filename)){
break;
}
}
if(num == file.gl_pathc){
printf("银行卡号不存在,已退出\n");
printf("按任意键退出\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return ;
}
// strcpy(r_buf.data.name, file.gl_pathv[num]);
r_buf.data.id = id;
r_buf.data.pid = getpid();
r_buf.type = CHECK;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
if(msgrcv(s2cmsgid,&r_buf, sizeof(struct C2SMSG) - sizeof(long), getpid(), 0) == -1){
perror("msgrcv err");
return;
}
// if(r_buf.data.id == id){
num = 0;
clears();
while(1){
printf("请输入密码\n");
scanf("%s", passwd);
clear();
if(! (id = strcmp(r_buf.data.passwd, passwd))){
clears();
printf("密码正确\n");
break;
}
else{
clears();
printf("密码或账号错误\n");
num ++;
}
if(num == 3){
clears();
W_buf.type = CHECK;
W_buf.data.id = -1;
if(msgsnd(c2smsgid, &W_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
printf("密码错误3次,已退出\n");
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
}
// clear();
// clears();
r_buf.data.pid = getpid();
r_buf.type = CHECK;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
clears();
if(msgrcv(s2cmsgid,&w_buf, sizeof(struct S2CMSG) - sizeof(long), getpid(), 0) == -1){
perror("msgrcv err");
return;
}
if(!strcmp(w_buf.info, "查询失败")){
printf("%s\n", w_buf.info);
}
else{
printf("%s\n", w_buf.info);
printf("账号 : %d\n", w_buf.id);
printf("户主 : %s\n", r_buf.data.name);
printf("余额 : %f\n", w_buf.money);
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
}
// }
}
//转账
//
void trans(){
int id = 0;
int i = 0;
char passwd[20] = {0};
char filename[64] = {0};
char ch = 0;
//int fd = 0;
int num = 0;
float money = 0;
struct C2SMSG r_buf;
struct S2CMSG w_buf;
printf("请输入银行卡号\n");
scanf("%d", &id);
clear();
sprintf(filename, "%d.txt", id);
//查找该账号是否存在
for(num = 0; num < file.gl_pathc; num ++){
if(! strcmp(file.gl_pathv[num] + len, filename)){
break;
}
}
if(num == file.gl_pathc){
clears();
printf("银行卡号不存在,已退出\n");
return ;
}
r_buf.data.id = id;
r_buf.data.pid = getpid();
r_buf.type = TRANS;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
if(msgrcv(s2cmsgid,&r_buf, sizeof(struct C2SMSG) - sizeof(long), getpid(), 0) == -1){
perror("msgrcv err");
return;
}
num = 0;
clears();
while(1){
printf("请输入密码\n");
scanf("%s", passwd);
clear();
if(! (id = strcmp(r_buf.data.passwd, passwd))){
clears();
printf("密码正确\n");
break;
}
else{
clears();
printf("密码或账号错误\n");
num ++;
}
if(num == 3){
clears();
printf("密码错误3次,已退出\n");
r_buf.type = TRANS;
r_buf.data.id = -1;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
}
num = 0;
i = 0;
while(1){
printf("请输入收款银行卡号\n");
scanf("%d", &id);
clear();
sprintf(filename, "%d.txt", id);
//查找该账号是否存在
for(num = 0; num < file.gl_pathc; num ++){
if(! strcmp(file.gl_pathv[num] + len, filename)){
break;
}
}
if(num == file.gl_pathc){
clears();
printf("银行卡号不存在\n");
i++;
}
else{
clears();
r_buf.data.o_id = id;
break;
}
if(i == 3){
clears();
printf("银行卡号输入错误3次,已退出\n");
printf("按任意键继续\n");
r_buf.type = TRANS;
r_buf.data.id = -1;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
}
num = 0;
while(1){
printf("卡号:%d\n", r_buf.data.id);
printf("余额:%f\n", r_buf.data.money);
printf("收款方卡号:%d\n", r_buf.data.o_id);
printf("请输入转账金额\n");
scanf("%f", &money);
clear();
if((money == 0 && num < 4) || (money < 0 && num < 4) || (money > r_buf.data.money && num < 4)){
clears();
printf("转账金额错误,请重新输入\n");
num ++;
}
else{
clears();
r_buf.data.money = r_buf.data.money - money;
// printf("%f\n", r_buf.data.money);
break;
}
if(num == 3){
clears();
printf("金额错误3次,已退出\n");
printf("按任意键继续\n");
r_buf.type = TRANS;
r_buf.data.id = -1;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
}
// clear();
// clears();
r_buf.data.pid = getpid();
r_buf.type = TRANS;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
if(msgrcv(s2cmsgid,&w_buf, sizeof(struct S2CMSG) - sizeof(long), getpid(), 0) == -1){
perror("msgrcv err");
return;
}
if(!strcmp(w_buf.info, "取款失败")){
printf("%s\n", w_buf.info);
}
else{
printf("%s\n", w_buf.info);
printf("账号 : %d\n", w_buf.id);
printf("户主 : %s\n", r_buf.data.name);
printf("余额 : %f\n", w_buf.money);
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
}
// }
}
//销户
void delac(){
int id = 0;
char passwd[20] = {0};
char filename[64] = {0};
//int fd = 0;
int num = 0;
char ch = 0;
//float money = 0;
struct C2SMSG r_buf;
struct S2CMSG w_buf;
//复制
printf("请输入请输入需要注销账户的银行卡号\n");
scanf("%d", &id);
clear();
sprintf(filename, "%d.txt", id);
//查找该账号是否存在
for(num = 0; num < file.gl_pathc; num ++){
if(! strcmp(file.gl_pathv[num] + len, filename)){
break;
}
}
if(num == file.gl_pathc){
printf("银行卡号不存在,已退出\n");
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return ;
}
// strcpy(r_buf.data.name, file.gl_pathv[num]);
r_buf.data.id = id;
r_buf.data.pid = getpid();
r_buf.type = DELAC;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
if(msgrcv(s2cmsgid,&r_buf, sizeof(struct C2SMSG) - sizeof(long), getpid(), 0) == -1){
perror("msgrcv err");
return;
}
num = 0;
while(1){
printf("请输入密码\n");
scanf("%s", passwd);
clear();
if(! (id = strcmp(r_buf.data.passwd, passwd))){
clears();
// printf("密码正确\n");
break;
}
else{
clears();
printf("密码或账号错误\n");
num ++;
}
if(num == 3){
printf("密码错误3次,已退出\n");
printf("按任意键继续\n");
r_buf.type = DELAC;
r_buf.data.id = -1;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
}
printf("即将销户的账号信息\n");
printf("账号 : %d\n", r_buf.data.id);
printf("户主 : %s\n", r_buf.data.name);
printf("余额 : %f\n", r_buf.data.money);
if(r_buf.data.money){
printf("账号余额不为0, 请先将存款取出\n");
printf("销户已退出\n");
printf("按任意键继续\n");
r_buf.type = DELAC;
r_buf.data.id = -1;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
printf("输入 y 确认注销账户\n");
scanf("%c", &ch);
clear();
if(ch != 'y' && ch != 'Y'){
r_buf.data.id = -1;
r_buf.type = DELAC;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
printf("已取消注销账户\n");
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
return;
}
// clear();
// clears();
r_buf.data.pid = getpid();
r_buf.type = DELAC;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
if(msgrcv(s2cmsgid,&w_buf, sizeof(struct S2CMSG) - sizeof(long), getpid(), 0) == -1){
perror("msgrcv err");
return;
}
clears();
printf("银行卡号 : %d\n", w_buf.id);
printf("账户状态 : %s\n", w_buf.info);
printf("按任意键继续\n");
while(1){
if(scanf("%c", &ch)){
clear();
clears();
break;
}
}
}
//清理缓存区
void clear(){
while(getchar() != '\n');
}
//清屏
void clears() {
printf("\033[2J\033[1;1H");
}
serve.c
#include <common.h>
void stop(int a);
int c2smsgid, s2cmsgid; //信息队列id
struct INFOR{
char pathname[128]; //可执行文件路径
char xname[32]; //可执行文件文件名
pid_t pid; //子进程pid
};
// 功能
struct INFOR infor[] = {{"/home/yyy/linux/银行项目/src/open", "open"}, //开户功能
{"/home/yyy/linux/银行项目/src/dep", "dep"},
{"/home/yyy/linux/银行项目/src/disdep", "disdep"},
{"/home/yyy/linux/银行项目/src/check", "check"},
{"/home/yyy/linux/银行项目/src/trans", "trans"},
{"/home/yyy/linux/银行项目/src/delac", "delac"}
};
int main(){
signal(2, stop);//信号改造
//创建消息队列
s2cmsgid = msgget(S2CKEY, IPC_CREAT | 0644);
if(s2cmsgid == -1){
perror("msgget err");
return -1;
}
c2smsgid = msgget(C2SKEY, IPC_CREAT | 0644);
if(c2smsgid == -1){
perror("msgget err");
return -1;//创建子进程
}
//创建子进程{}
for(int i = 0; i < sizeof(infor) / sizeof(infor[0]); i++){
infor[i].pid = fork();
if(infor[i].pid == 0){
execl(infor[i].pathname, infor[i].xname, NULL);
}
}
printf("ctrl + C退出服务器\n");
while(1){};
}
//退出函数
void stop(int a){
for(int i = 0; i < sizeof(infor) / sizeof(infor[0]); i++){
kill(infor[i].pid, 9);
}
msgctl(c2smsgid, IPC_RMID, NULL);
msgctl(s2cmsgid, IPC_RMID, NULL);
exit(0);
}
dep.c
#include <common.h>
//函数声明
int CREATID();
int save_info(struct C2SMSG r_buf);
//全局变量
int s2cmsgid, c2smsgid;
int main(){
int fd = 0;
char filename[64] = {0};
pid_t pid = 0;
printf("服务器存款功能启动成功\n");
//访问消息队列
s2cmsgid = msgget(S2CKEY, IPC_CREAT | 0644);
if(s2cmsgid == -1){
perror("msgget err");
return -1;
}
c2smsgid = msgget(C2SKEY, IPC_CREAT | 0644);
if(c2smsgid == -1){
perror("msgget err");
return -1;
}
//创建结构体
struct C2SMSG r_buf;
struct S2CMSG w_buf;
while(1){
//接收消息队列信息
printf("存款功能准备第一次接收信息\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), DEP, 0) == -1){
perror("msgrcv err");
return 0;
}
printf("存款功能第一次接收信息完毕\n");
printf("存款账户:%d\n", r_buf.data.id);
sprintf(filename, "%d.txt", r_buf.data.id);
fd = open(filename, O_RDONLY);
if(fd == -1){
perror("open err");
return -1;
}
pid = r_buf.data.pid;
read(fd, &r_buf, sizeof(struct C2SMSG));
close(fd);
//printf("%s\n", r_buf.data.passwd);
r_buf.type = pid;
printf("存款功能准备第一次发送信息\n");
if(msgsnd(s2cmsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return 0;
}
printf("存款功能第一次发送信息完成\n");
// w_buf.type = r_buf.data.pid;
// w_buf.id = r_buf.data.id;
// w_buf.money = r_buf.data.money;
//接收消息队列信息n
printf("存款功能准备第二次接收信息\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), DEP, 0) == -1){
perror("msgrcv err");
return 0;
}
printf("存款功能第二次接收信息完成\n");
if(r_buf.data.id == -1){
printf("客户端异常操作,存款功能已重置\n");
continue;
}
w_buf.type = r_buf.data.pid;
w_buf.id = r_buf.data.id;
w_buf.money = r_buf.data.money;
if(save_info(r_buf) == -1){
strcpy(w_buf.info, "存款失败");
}
else{
strcpy(w_buf.info, "存款成功");
}
printf("存款功能准备第二次发送信息\n");
if(msgsnd(s2cmsgid, &w_buf, sizeof(struct S2CMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return 0;
}
printf("存款功能第二次发送数据完毕\n");
printf("账户金额:%f\n", r_buf.data.money);
printf("存款完毕\n");
}
}
//保存信息
int save_info(struct C2SMSG r_buf){
char filename[64] = {0};
sprintf(filename, "%d.txt", r_buf.data.id);
int fd = open(filename, O_WRONLY);
if(fd == -1){
perror("open err");
return -1;
}
write(fd, &r_buf, sizeof(r_buf));
close(fd);
return 0;
}
disdep.c
#include <common.h>
//函数声明
int CREATID();
int save_info(struct C2SMSG r_buf);
//全局变量
int s2cmsgid, c2smsgid;
int main(){
printf("服务器取款功能启动成功\n");
int fd = 0;
char filename[64] = {0};
pid_t pid = 0;
//访问消息队列
s2cmsgid = msgget(S2CKEY, IPC_CREAT | 0644);
if(s2cmsgid == -1){
perror("msgget err");
return -1;
}
c2smsgid = msgget(C2SKEY, IPC_CREAT | 0644);
if(c2smsgid == -1){
perror("msgget err");
return -1;
}
//创建结构体
struct C2SMSG r_buf;
struct S2CMSG w_buf;
while(1){
//接收消息队列信息
//接收消息队列信息
printf("取款功能准备第一次接收信息\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), DISDEP, 0) == -1){
perror("msgrcv err");
return 0;
}
printf("取款功能第一次接收信息完成\n");
printf("取款账户:%d\n", r_buf.data.id);
sprintf(filename, "%d.txt", r_buf.data.id);
fd = open(filename, O_RDONLY);
if(fd == -1){
perror("open err");
return -1;
}
pid = r_buf.data.pid;
read(fd, &r_buf, sizeof(struct C2SMSG));
close(fd);
r_buf.type = pid;
printf("取款功能准备第一次发送信息\n");
if(msgsnd(s2cmsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return 0;
}
printf("取款服务器第一次发送信息完成\n");
printf("取款服务准备第二次接收数据\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), DISDEP, 0) == -1){
perror("msgrcv err");
return 0;
}
printf("取款服务第二次接收信息完成\n");
if(r_buf.data.id == -1){
printf("客户端操作异常,取款功能已重置\n");
continue;
}
w_buf.type = r_buf.data.pid;
w_buf.id = r_buf.data.id;
w_buf.money = r_buf.data.money;
if(save_info(r_buf) == -1){
strcpy(w_buf.info, "取款失败");
}
else{
strcpy(w_buf.info, "取款成功");
}
printf("取款功能准备第二次发送信息\n");
if(msgsnd(s2cmsgid, &w_buf, sizeof(struct S2CMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return 0;
}
printf("取款服务第二次发送数据完成\n");
printf("账户金额:%f\n", r_buf.data.money);
printf("取款完成\n");
}
}
//保存信息
int save_info(struct C2SMSG r_buf){
char filename[64] = {0};
sprintf(filename, "%d.txt", r_buf.data.id);
int fd = open(filename, O_WRONLY);
if(fd == -1){
perror("open err");
return -1;
}
write(fd, &r_buf, sizeof(r_buf));
close(fd);
return 0;
}
check.c
#include <common.h>
//函数声明fff
int CREATID();
int save_info(struct C2SMSG r_buf);
void clears();
//全局变量
int s2cmsgid, c2smsgid;
int main(){
printf("服务器查询功能启动成功\n");
int fd = 0;
char filename[64] = {0};
pid_t pid = 0;
//访问消息队列
s2cmsgid = msgget(S2CKEY, IPC_CREAT | 0644);
if(s2cmsgid == -1){
perror("msgget err");
return -1;
}
c2smsgid = msgget(C2SKEY, IPC_CREAT | 0644);
if(c2smsgid == -1){
perror("msgget err");
return -1;
}
//创建结构体
struct C2SMSG r_buf;
struct S2CMSG w_buf;
while(1){
//接收消息队列信息
printf("查询功能准备第一次接收信息\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), CHECK, 0) == -1){
perror("msgrcv err");
return 0;
}
printf("查询功能第一次接收信息完成\n");
printf("查询账户为:%d\n", r_buf.data.id);
sprintf(filename, "%d.txt", r_buf.data.id);
fd = open(filename, O_RDONLY);
if(fd == -1){
perror("open err");
return -1;
}
pid = r_buf.data.pid;
read(fd, &r_buf, sizeof(struct C2SMSG));
close(fd);
r_buf.type = pid;
printf("查询功能准备第一次发送信息\n");
if(msgsnd(s2cmsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return 0;
}
printf("查询功能第一次发送信息完成\n");
printf("查询功能准备第二次接收信息\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), CHECK, 0) == -1){
perror("msgrcv err");
return 0;
}
printf("查询功能第二次接收信息完成\n");
if(r_buf.data.id == -1){
printf("客户端错误操作,查询功能已重置\n");
continue;
}
w_buf.type = r_buf.data.pid;
w_buf.id = r_buf.data.id;
w_buf.money = r_buf.data.money;
if(save_info(r_buf) == -1){
strcpy(w_buf.info, "查询失败");
}
else{
strcpy(w_buf.info, "查询成功");
}
printf("查询功能准备第二次发送信息\n");
if(msgsnd(s2cmsgid, &w_buf, sizeof(struct S2CMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return 0;
}
printf("查询功能第二次发送信息完成\n");
printf("账户金额:%f\n", r_buf.data.money);
printf("查询完成\n");
}
}
//保存信息
int save_info(struct C2SMSG r_buf){
char filename[64] = {0};
sprintf(filename, "%d.txt", r_buf.data.id);
int fd = open(filename, O_WRONLY);
if(fd == -1){
perror("open err");
return -1;
}
write(fd, &r_buf, sizeof(r_buf));
close(fd);
return 0;
}
//清屏
void clears() {
printf("\033[2J\033[1;1H");
}
trans.c
#include <common.h>
//函数声明
int CREATID();
int save_info(struct C2SMSG r_buf);
//全局变量
int s2cmsgid, c2smsgid;
int main(){
int fd = 0;
pid_t pid = 0;
char filename[64] = {0};
printf("服务器转账功能启动成功\n");
//访问消息队列
s2cmsgid = msgget(S2CKEY, IPC_CREAT | 0644);
if(s2cmsgid == -1){
perror("msgget err");
return -1;
}
c2smsgid = msgget(C2SKEY, IPC_CREAT | 0644);
if(c2smsgid == -1){
perror("msgget err");
return -1;
}
//创建结构体
struct C2SMSG r_buf;
struct S2CMSG w_buf;
while(1){
//接收消息队列信息
printf("转账功能准备第一次接收信息\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), TRANS, 0) == -1){
perror("msgrcv err");
return 0;
}
printf("转账功能第一次接收信息完成\n");
sprintf(filename, "%d.txt", r_buf.data.id);
fd = open(filename, O_RDONLY);
if(fd == -1){
perror("open err");
return -1;
}
pid = r_buf.data.pid;
read(fd, &r_buf, sizeof(struct C2SMSG));
close(fd);
//printf("%s\n", r_buf.data.passwd);
r_buf.type = pid;
printf("转账功能准备第一次发送信息\n");
if(msgsnd(s2cmsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return 0;
}
printf("转账功能第一次发送信息完成\n");
printf("转账功能准备第二次接收信息\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), TRANS, 0) == -1){
perror("msgrcv err");
return 0;
}
printf("转账功能第二次接收信息完成\n");
if(r_buf.data.id == -1){
printf("客户端异常操作,转账功能已重置\n");
continue;
}
w_buf.type = r_buf.data.pid;
w_buf.id = r_buf.data.id;
w_buf.money = r_buf.data.money;
//修改余额
if(save_info(r_buf) == -1){
strcpy(w_buf.info, "转账失败");
}
else{
strcpy(w_buf.info, "转账成功");
}
printf("转账功能准备第二次发送信息\n");
if(msgsnd(s2cmsgid, &w_buf, sizeof(struct S2CMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return 0;
}
printf("转账功能第二次发送信息完成\n");
printf("账户金额:%f\n", r_buf.data.money);
printf("转账成功\n");
}
}
//保存信息
int save_info(struct C2SMSG r_buf){
char filename1[64] = {0};
char filename2[64] = {0};
struct C2SMSG w_buf1, w_buf2;
sprintf(filename1, "%d.txt", r_buf.data.id);
int fd1 = open(filename1, O_RDWR);
if(fd1 == -1){
perror("open err");
return -1;
}
sprintf(filename2, "%d.txt", r_buf.data.o_id);
int fd2 = open(filename2, O_RDWR);
if(fd2 == -1){
perror("open err");
return -1;
}
read(fd1, &w_buf1, sizeof(struct C2SMSG));
read(fd2, &w_buf2, sizeof(struct C2SMSG));
// printf("%f\n%f\n%f\n", w_buf1.data.money, w_buf2.data.money, r_buf.data.money);
w_buf2.data.money = w_buf1.data.money - r_buf.data.money + w_buf2.data.money;
w_buf1.data.money = r_buf.data.money;
// printf("%f\n", w_buf1.data.money);
// printf("%f\n", w_buf2.data.money);
lseek(fd1, 0, 0);
write(fd1, &w_buf1, sizeof(struct C2SMSG));
close(fd1);
lseek(fd2, 0, 0);
write(fd2, &w_buf2, sizeof(struct C2SMSG));
close(fd2);
return 0;
}
open.c
#include <common.h>
//函数声明
int CREATID();
void save_info(struct C2SMSG r_buf);
//全局变量
int s2cmsgid, c2smsgid;
int main(){
printf("服务器开户功能启动成功\n");
//访问消息队列
s2cmsgid = msgget(S2CKEY, IPC_CREAT | 0644);
if(s2cmsgid == -1){
perror("msgget err");
return -1;
}
c2smsgid = msgget(C2SKEY, IPC_CREAT | 0644);
if(c2smsgid == -1){
perror("msgget err");
return -1;
}
//创建结构体
struct C2SMSG r_buf;
struct S2CMSG w_buf;
while(1){
//接收消息队列信息
printf("开户服务准备第一次接收信息\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), OPEN, 0) == -1){
perror("msgrcv err");
return 0;
}
w_buf.type = r_buf.data.pid;
w_buf.id = CREATID();
r_buf.data.id = w_buf.id;
w_buf.money = r_buf.data.money;
printf("开户服务第一次接收信息完成\n");
if(w_buf.id == -1){
strcpy(w_buf.info, "开户失败");
}
else{
strcpy(w_buf.info, "开户成功");
save_info(r_buf);
}
printf("开户服务准备第一次发送信息\n");
if(msgsnd(s2cmsgid, &w_buf, sizeof(struct S2CMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return 0;
}
printf("开户服务第一次发送信息完成\n");
printf("账户金额:%f\n", w_buf.money);
printf("开户成功\n");
}
}
//创建银行卡号
int CREATID(){
int init_id = 20230816;
int fd = 0;
if(((fd = open("id.txt", O_RDWR | O_CREAT, 0664)) == -1)){
perror("1open err");
return -1;
}
if((read(fd, &init_id, sizeof(init_id))) == -1){
perror("read err");
return -1;
}
init_id ++;
lseek(fd, 0, 0);
write(fd, &init_id, sizeof(init_id));
close(fd);
return init_id;
}
//保存信息
void save_info(struct C2SMSG r_buf){
char filename[64] = {0};
sprintf(filename, "%d.txt", r_buf.data.id);
int fd = open(filename, O_WRONLY | O_CREAT, 0664);
if(fd == -1){
perror("open err");
return;
}
write(fd, &r_buf, sizeof(r_buf));
close(fd);
}
delac.c
#include <common.h>
//函数声明
int CREATID();
int save_info(struct C2SMSG r_buf);
//全局变量
int s2cmsgid, c2smsgid;
int main(){
int fd = 0;
pid_t pid;
char filename[64] = {0};
printf("服务器销户功能启动成功\n");
//访问消息队列
s2cmsgid = msgget(S2CKEY, IPC_CREAT | 0644);
if(s2cmsgid == -1){
perror("msgget err");
return -1;
}
c2smsgid = msgget(C2SKEY, IPC_CREAT | 0644);
if(c2smsgid == -1){
perror("msgget err");
return -1;
}
//创建结构体
struct C2SMSG r_buf;
struct S2CMSG w_buf;
while(1){
//接收消息队列信息
printf("销户功能准备第一次接收信息\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), DELAC, 0) == -1){
perror("msgrcv err");
return 0;
}
printf("销户功能第一次接收信息完成\n");
printf("销户账号:%d\n", r_buf.data.id);
sprintf(filename, "%d.txt", r_buf.data.id);
fd = open(filename, O_RDONLY);
if(fd == -1){
perror("open err");
return -1;
}
pid = r_buf.data.pid;
read(fd, &r_buf, sizeof(struct C2SMSG));
close(fd);
r_buf.type = pid;
printf("销户功能准备第一次发送信息\n");
if(msgsnd(s2cmsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return 0;
}
printf("销户功能第一次发送信息完成\n");
printf("销户功能准备第二次接收信息\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), DELAC, 0) == -1){
perror("msgrcv err");
return 0;
}
printf("销户功能第二次接收信息完毕\n");
if(r_buf.data.id == -1){
printf("客户端异常操作,销户功能已重置\n");
continue;
}
w_buf.type = r_buf.data.pid;
w_buf.id = r_buf.data.id;
w_buf.money = r_buf.data.money;
if(save_info(r_buf) == -1){
strcpy(w_buf.info, "销户失败");
}
else{
strcpy(w_buf.info, "销户成功");
}
printf("销户功能准备第二次发送信息\n");
if(msgsnd(s2cmsgid, &w_buf, sizeof(struct S2CMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return 0;
}
printf("销户功能第二次发送信息完成\n");
printf("销户完成\n");
}
}
//保存信息
int save_info(struct C2SMSG r_buf){
char filename[64] = {0};
sprintf(filename, "%d.txt", r_buf.data.id);
int fd = unlink(filename);
if(fd == -1){
perror("unlink err");
return -1;
}
return 0;
}
项目开发过程所遇到的bug
忘记考虑 == 运算符的优先级高于 =
if((fd = open("id.txt", O_RDWR | O_CREAT, 0664) == -1)){
perror("1open err");
return -1;
}
if((read(fd, &init_id, sizeof(init_id))) == -1){
perror("read err");
return -1;
}
分析
open("id.txt", O_RDWR | O_CREAT, 0664) == -1 的值为0,
导致fd的值为0,而0表示标准输入,所以read从键盘读取内容,
导致刚开始开户的时候升序卡住,等待标准输入,并且会导致刚开始的银行卡号不正确
客户端和服务器的一个功能里面进行了多次消息队列的读取和发送,客户端第一次读取服务器发送的消息,之后客户端在判断用户操做非法后,就退出了客户端的功能函数,但服务器并不知情,仍然在等待客户端功能函数第二次发送消息,会导致客户端和服务器的信息传递错位,所以在服务器第二次接收消息后要进行判断,如果为错误消息则重置该功能,否则继续运行
//用户操作非法客户端功能函数退出,并向服务器发送错误信息
//让id = 0 并且发送给服务器
if(num == 3){
clears();
printf("密码错误3次,已退出\n");
printf("按任意键继续\n");
printf("客户端存款功能准备发送错误信息\n");
r_buf.type = DISDEP;
r_buf.data.id = -1;
if(msgsnd(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), 0) == -1){
perror("msgsnd err");
return;
}
}
//接收消息队列信息
//并且判断id是否为 -1, 如果id == -1, 重置服务器该模块功能,方便下次调用
printf("存款系统第二次接收信息开始\n");
if(msgrcv(c2smsgid, &r_buf, sizeof(struct C2SMSG) - sizeof(long), DEP, 0) == -1){
perror("msgrcv err");
return 0;
}
printf("存款系统第二次接收信息完毕\n");
if(r_buf.data.id == -1){
continue;
}
使用glob函数时,忘记剪切出文件的文件名, glob函数所获取的文件名,都带有地址,所以可以通过指针偏移来去掉路径
glob_t file = {0};
glob("/home/yyy/linux/2银行/src/*.txt", 0, NULL, &file); //获取所有账号文件
len = strlen("/home/yyy/linux/2银行/src/");
for(int i = 0; i < file.gl_pathc, i++){
strcpy(file.gl_pathv[i], file.gl_pathv[i] + len);
}
运行结果展示