首页 > 系统相关 >Linux下使用消息队实现 ATM 自动取款机功能

Linux下使用消息队实现 ATM 自动取款机功能

时间:2023-08-19 18:33:10浏览次数:27  
标签:return Linux buf ATM 取款机 printf sizeof data id

Linux下使用消息队实现 ATM 自动取款机功能

要求功能:

         (1)创建账户(2)存款(3)取款(4)查询(5)转账(6)退出(7)销户

用到的知识点:

      文件操作--创建账户的时候要把用户名,密码,余额,银行卡号。。。。(每个银行卡号单独存放一个文件)

创建父子进程

进程通信----消息队列

模块化编程

项目分析:

1、实现功能用到进程间通信

1)通信要求两个进程实现两个进程分别完成什么任务??站在用户的角度去考虑这个问题:例如:你去银行办卡的场景

你:我要办卡

银行职员:请出示你的相关信息

                         你:交出身份证    银行职员:开始一系列的操作(录入信息,开账户等),紧接着要求你输入密码

                         你:输入密码

                         银行职员:请确认密码

                         你:再次输入

银行职员:系统会自动给你分配一个卡号

                         银行职员:银行卡余额不能为空,请存款

                         你:交出100元

                         银行职员:拿走你的钱,在你的账户输入100

                                   ............

                                   ............

从这个角度来讲你和银行职员就是两个不同的进程,你们分别的任务有:银行职员根据你的提示信息为你办卡、存款、取款、查询、转账、退出、销户操作,而你要做的就是给出相应的操作提示

2)进程间通信的选取

                         规定使用消息队列

整体思路

该项目主要分为客户端和服务器两大模块,客户端只用来处理客户的操作,并将数据发送给服务器,并且客户端不能直接访问存储的数据,所有数据由服务器访问并修改,并通过消息队列发送给客户端。服务器通过创建子程序,每个子程序调用不同的可执行文件来实现银行终端的功能。

模块分析

common.h头文件

包含了整个项目所需的头文件和数据类型

  1. C2SKEY和S2CKEY:客户端和服务器端消息队列创建时的键值
  2. enum opt {OPEN = 1, DEP, DISDEP, CHECK, TRANS, DELAC, QUIT};//办卡 存款 取款 查询 转账 销户 退出,定义了枚举菜单,消息队列通信时的消息类型
  3. 定义了传递消息的数据结构:
  1. DATA:账号信息的结构体 账号 户主 余额 密码 转账账户
  2. C2SMSG:客户端到服务器的消息格式 data结构体和 tyoe消息类型
  3. S2CMSG:服务器到客户端的响应消息格式 type消息类型, 账号 余额 户主

serve.c 服务器

主进程通过 for 循环来循环调用 fork 函数创建子进程,每个子进程独立处理一项功能,每个子进程通过消息队列和客户端进行通信,并使用消息改造函数改造二号信号,当服务器收到二号信号时,将会杀死所有子程序,并且删除消息队列,退出服务器

main()函数

  1. 创建消息队列
  2. 根据 infor 数组,通过fork函数创建子进程,infor 数组包含可执行文件的路径和文件名
  3. 每个子进程调用execl函数来执行相应的可执行文件,实现相应功能
  4. 主进程等待二号信号来调用stop()函数

stop()函数

  1. 收到二号信号时被调用
  2. 遍历杀死每个子进程
  3. 删除消息队列
  4. 退出服务器

client.c 客户端

创建消息队列和服务器进行通信,通过菜单界面提示用户相应的功能并调用相应的功能函数,功能函数会根据用户的输入发送消息给服务器来获取相应的数据,但客户端本身并不能操作数据,客户端接收服务器的消息结果并显示给用户,通过主循环来实现客户端的循环运行。

main()函数 循环调用,整个客户端框架

  1. 访问服务器消息队列
  2. 循环调用 menu() 函数来显示菜单并获取选择
  3. 根据选择调用不同的功能函数

menu()函数 菜单

  1. 通过枚举变量打印菜单
  2. 获取用户选择并返回相应编号
  3. 调用 glob() 函数来查询指定目录下的所有账号文件,每次菜单被调用的时候就刷新一次

CREATACCOUNT() 函数 创建银行卡号

  1. 获取用户输入的账号信息并判断是否合法
  2. 构造访问服务器的消息结构体
  3. 通过消息队列将创建的账号信息发送到服务器
  4. 接收并处理服务器返回的结果
  5. 完成办卡功能

dep() 函数 存款 disdep() 函数 取款 check() 函数 查询 delac() 函数 销户 trans() 函数 转账

这些函数思路基本一致,所以整体列出

  1. 获取用户输入的账号
  2. 使用字符串拼接函数拼接成账号文件名,通过遍历来与 glob() 函数获取的文件名比较
  3. 查询到账号文件向服务器发送请求,服务器返回账号信息,否则打印错误信息并退出功能函数
  4. 根据账号信息来确定用户操作是否合法,如果非法则退出功能函数,并向服务器发送错误信息,使服务器的相应功能重置为初始状态方便下次访问,如果用户操作合法,向服务器发送操作后的账号信息,服务器接收并作出相应处理
  5. 接收服务器的返回结果并打印

clear() 和 clears() 清理函数

  1. 清理输入缓冲区和屏幕

open.c 服务器办卡功能

通过消息队列接收客户端的账号信息,通过字符串拼接将银行卡号和 .txt 拼接起来作为账户i信息文件名,并创建相应的账号文件来保存信息

main() 函数

  1. 创建消息队列
  2. 循环接收客户端的办卡请求
  3. 调用 CREATID() 生成新账号
  4. 调用 save_info() 来保存文件
  5. 构造响应消息,发送给客户端

CREATID() 函数 生成银行卡号

  1. 打开账号ID记录文件id.txt
  2. 读取当前最大账号ID
  3. 递增生成新账号
  4. 写入新ID,返回给主函数

save_info()函数

  1. 根据账号创建对应数据文件
  2. 将办卡信息写入该文件

dep.c 服务器存款功能 disdep.c 服务器取款功能 check.c 服务器查询功能 trans.c 服务器转账功能 delac.c 服务器销户功能

这些模块功能基本一致,所以整体列出

  1. 创建消息队列
  2. 接收客户端所发送的账户文件名
  3. 向客户端发送账户的具体信息,如银行卡号,余额,户主等等
  4. 再次接收客户端所发送的信息,并进行判断,让如果是错误信息则初始化该模块功能,方便下次调用,如果是正确信息则继续服务器该功能,继续向下执行,最后返回处理结果给客户端

代码展示

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);
}

运行结果展示

Linux下使用消息队实现 ATM 自动取款机功能_系统编程

Linux下使用消息队实现 ATM 自动取款机功能_消息队列_02

Linux下使用消息队实现 ATM 自动取款机功能_linux_03

标签:return,Linux,buf,ATM,取款机,printf,sizeof,data,id
From: https://blog.51cto.com/u_16158769/7151064

相关文章

  • CHAPTER 7 Linux Operating System Services linux 系统服务
     /usr/include/asm-generic/unistd.h  /usr/include/errno.h/usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h  ......
  • 【逍遥西游中变】Linux手工服务端+安卓苹果双端
    5月整理大话回合手游【逍遥西游中变】Linux手工服务端+充值后台+安卓苹果双端压缩包内有详细的视频搭建教程,亲测有效,点击下面链接  提取码:8co9......
  • linux基础命令
    1、显示了系统名称和内核版本cat/etc/issue2、显示系统名、节点名称、操作系统的发行版号、操作系统版本、运行系统的机器ID号uname-a3、查看磁盘空间占用情况df-hl4、查看内存使用情况free-mtotal内存总数used已经使用的内存数:free空闲的内存数shared当前已经废弃不用,......
  • linux root用户密码输入正确还是提示access denied
    问题:之前用远程工具连接一直都是好的,第二天上班找开远程工具要输root的密码了,输入用户密码后还是无效,可以确定用户密码是对的,其中有一个远程工具一直是连着的就没有问题。排查问题:1、相接用passwd修改密码,无效2、查看用户是否被锁定,也没有锁3、因为在前一天晚上我删了liunx中/......
  • Virtualbox安装Linux使用2560以上高分辨率黑屏
    Virtualbox安装Linux后,通过VirtualBox的视图菜单默认只有1920的分辨率可供选择,想要使用更高分辨率(比如4K)需要在Linux系统的设置里选择。但是,通过Linux系统菜单设置分辨率达到2560时,虚拟机就会黑屏,只有鼠标。此时系统仍然正常运行,按esc可取消当前设置,按回车会确认当前设置,然后就黑......
  • linux基础
    1.计算机基础美团单车内存-ram读写速度快-运行程序-程序从闪存加载到[内存]中运行掉电数据丢失临时存储数据闪存-rom读写速度慢掉电数据不丢失-存储数据-存储信息永久存储数据程序运行下载微信-闪存手机:12+25612-内存256-闪存操作系统中的......
  • Linux网络编程(epoll函数的使用)
    (文章目录)前言本篇文章我们讲解epoll函数的使用方法,epoll相比于poll来说性能方面有所提升和改进。一、epoll概念特点讲解epoll是Linux上一种高性能的多路复用机制,用于监视大量文件描述符并在它们就绪时通知应用程序。它是在select和poll的基础上进一步优化和改进而来......
  • linux之shell脚本quickStart
    这篇文章主要参考于《跟老男孩学linux运维:Shell编程实战》,方便写shell脚本时参考,只列一些shell脚本中的容易混淆的知识点。目录1变量1.1普通变量1.2shell特殊变量1.3shell特殊扩展变量2运算符2.1空格2.2(())与[]2.3||与&&3常用命令3.1read3.2echo3.3eval3.4双......
  • linux云服务器状态上报
    统计某文件夹下文件的个数ls-l|grep “^-”|wc-l统计某文件夹下目录的个数ls-l|grep“^d”|wc-l统计文件夹下文件的个数,包括子文件夹里的。ls-lR|grep“^-”|wc-l统计文件夹下目录的个数,包括子文件夹里的。ls-lR|grep“^d”|wc-l说明:ls-l长列表输出该目录下文件信息(......
  • 部署Kafka+ZK及其日志采集实战(系统版本:linux_CentOs_7.8)
    部署ZKdockerrun-d--namezookeeper-p2181:2181-twurstmeister/zookeeper部署Kafka-p9092:9092\-eKAFKA_BROKER_ID=0\--envKAFKA_HEAP_OPTS=-Xmx256M\--envKAFKA_HEAP_OPTS=-Xms128M\-eKAFKA_ZOOKEEPER_CONNECT=[内网ip]:2181\-eKAFKA_ADVERTISED......