C语言小项目 银行管理系统 基于socket套接字 网络通信

以下是客户端和服务端的代码
至于相关的头文件和封装好的工具函数请从以下网址下载:https://gitee.com/follllll/socket_bank

client:

#include "tools.h"
#include <stdio.h>
#include "bank.h"
#define BUF_SIZE (4096)

void sub_menu(void);
void save(void);
void take(void);
void query(void);
void transfer(void);
void repass(void);
Account acc={1,"1","1","1",1,0};
int cli_fd;
// 主菜单
void main_menu(void)
{
	system("clear");
	puts("******欢迎使用指针银行******");
	puts("1、开户		2、登陆");
	puts("3、销户		4、解锁");
	puts("0、退出");
}
void open_acc(void)
{
	acc.operate=M_OPEN;
	printf("请输入身份证号:");
	get_str(acc.card,10);
	printf("请输入开户金额:");
	scanf("%f",&acc.balance);
}
// 登陆
void login(void)
{
	acc.operate = M_LOGIN;
	printf("请输入银行卡号:");
	get_str(acc.bank,20);
	printf("请输入密码:");
	get_pass(acc.pass,7,true);
	
	char msg[4096];
	sprintf(msg,"%d %s %s %s %f %d",acc.operate,acc.bank,acc.card,acc.pass,acc.balance,acc.islock);
	//发送数据
	int ret_size=write(cli_fd,msg,strlen(msg)+1);
	
	//接收返回信息
	int recv_size = read(cli_fd,msg,sizeof(msg));
	//打印是否登录成功信息
	puts(msg);
	anykey_continue();
	if('Y' != msg[0])
	{
		return;
	}
	for(;;)
	{
		sub_menu();
		switch(get_cmd('1','6')-'0'+4)
		{
		case M_SAVE: 	save();		break;	// 存款
		case M_TAKE: 	take();		break;	// 取款
		case M_QUERY: 	query();	break;	// 查询
		case M_TRANSFER:transfer();	break;	// 转账
		case M_REPASS:	repass();	break;	// 改密
		default: exit(EXIT_SUCCESS);break;	// 退出
		}
		char buf[4096];
		sprintf(buf,"%d %s %s %s %f %d",acc.operate,acc.bank,acc.card,acc.pass,acc.balance,acc.islock);
		//发送数据
		write(cli_fd,buf,strlen(buf)+1);
		//接收返回信息
		read(cli_fd,buf,sizeof(msg));
		// 显服务端执行的结果
		printf("%s\n",buf);
		anykey_continue();
	}
}

// 销户
void destory(void)
{
	acc.operate = M_DESTORY;
	printf("请输入银行卡号:");
	get_str(acc.bank,20);
	printf("请输入身份证号:");
	get_str(acc.card,20);
	printf("请输入密码:");
	get_pass(acc.pass,7,true);
}

// 解锁
void unlock(void)
{
	acc.operate = M_UNLOCK;
	printf("请输入银行卡号:");
	get_str(acc.bank,20);
	printf("请输入身份证号:");
	get_str(acc.card,20);
	printf("请输入密码:");
	get_pass(acc.pass,7,true);
}

// 子菜单
void sub_menu(void)
{
	system("clear");
	puts("********登陆成功********");
	puts("1、存款		2、取款");
	puts("3、查询		4、转账");
	puts("5、改密		6、退出");
}


// 存款
void save(void)
{
	acc.operate = M_SAVE;
	printf("请输入存款金额:");
	scanf("%f",&acc.balance);
}

// 取款
void take(void)
{
	acc.operate = M_TAKE;
	printf("请输入取款金额:");
	scanf("%f",&acc.balance);
}

// 查询
void query(void)
{
	acc.operate = M_QUERY;
}

// 转账
void transfer(void)
{
	acc.operate = M_TRANSFER;
	printf("请输入目标银行卡号:");
	get_str(acc.card,20);
	printf("请输入转账金额:");
	scanf("%f",&acc.balance);
}

// 改密
void repass(void)
{
	char pass1[10] = {} , pass2[10] = {};
	printf("请输入新密码:");
	get_pass(pass1,10,true);
	printf("请再次输入新密码:");
	get_pass(pass2,10,true);
	acc.operate = M_REPASS;
	
	if(strcmp(pass1,pass2))
	{
		//puts("两次输入的密码不相同,修改失败!");
		strcpy(acc.pass,"-1");
	}
	else if(0==strcmp(pass1,acc.pass))
	{
		//puts("密码不能和原密码相同");
		strcpy(acc.pass,"-2");
		
	}
	else
	{
		
		strcpy(acc.pass,pass1);
	}
}
int main()
{
	// 创建socket
	cli_fd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > cli_fd)
	{
		perror("socket");
		return -1;
	}

	// 准备地址
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(6789);
	addr.sin_addr.s_addr = inet_addr("10.0.2.15");

	// 连接
	if(connect(cli_fd,(struct sockaddr*)&addr,sizeof(addr)))
	{
		perror("connect");
		return -1;
	}
	for(;;)
	{
		while(1)
		{
			main_menu();
			switch(get_cmd('0','7')-'0')
			{
				case M_EXIT:	return 0;	break;		// 退出
				case M_OPEN:	open_acc();	break;		// 开户
				case M_LOGIN: 	login();	continue;	// 登陆
				case M_DESTORY: destory();	break;		// 销户
				case M_UNLOCK:	unlock();	break; 		// 解锁
			}
			char buf[4096];
			sprintf(buf,"%d %s %s %s %f %d",acc.operate,acc.bank,acc.card,acc.pass,acc.balance,acc.islock);
			//发送数据
			int ret_size=write(cli_fd,buf,strlen(buf)+1);
			//接收返回信息
			int recv_size = read(cli_fd,buf,4096);
			printf("%s\n",buf);
			anykey_continue();
		}
	}
}

server:

#include "tools.h"
#include <stdio.h>
#include "bank.h"
#include<signal.h>
#define BUF_SIZE (4096)
void open_acc();
void login();
void destory();
void unlock();
void save();
void transfer();
void repass();
void take();
void query();


int bank_id=1001;
int svr_fd;


//ctrl c杀死进程
void sigint (int signum)
{
	close(svr_fd);
	printf("关闭");
	exit(0);
}
//打印所有信息(用于查找bug)
void show(Account*acc)
{
	printf("%d %s %s %s %f %d\n",acc->operate,acc->bank,acc->card,acc->pass,acc->balance,acc->islock);
}

void * server(void* arg)
{
	int cli_fd=*(int *) arg;
	Account* acc=malloc(sizeof(Account));
	for(;;)
	{
		char buf[4096];
		int recv_size=read(cli_fd,buf,BUF_SIZE);
		if(0 >= recv_size )
		{
			printf("客户端%d退出\n",cli_fd);
			close(cli_fd);
			pthread_exit(NULL);
		}
		sscanf(buf,"%d %s %s %s %f %d",&acc->operate,acc->bank,acc->card,acc->pass,&acc->balance,&acc->islock);
		switch(acc->operate)
		{
			case M_OPEN:open_acc(acc,buf);break;		//开户
			case M_LOGIN:login(acc,buf);break;			//登录
			case M_DESTORY:destory(acc,buf);break;		//销户
			case M_UNLOCK:unlock(acc,buf);break;		//解锁
			case M_SAVE:save(acc,buf);break;			//存钱
			case M_TAKE:take(acc,buf);break;			//取款
			case M_QUERY:query(acc,buf);break;			//查询
			case M_TRANSFER:transfer(acc,buf);break;	//转账
			case M_REPASS:repass(acc,buf);	break;		//改密码
		}
		write(cli_fd,buf,strlen(buf)+1);
	}
}

//开户
void open_acc(Account * acc,char * buf)
{
	puts("用户正在开户");
	sprintf(acc->bank,"%d",bank_id);
	sprintf(acc->pass,"123456");
	acc->islock=0;
	char path[256];
	sprintf(path,"acc/%s",acc->bank);
	int fd = open(path,O_WRONLY|O_CREAT|O_EXCL,0644);
	if(0>fd)
	{
		error("open");
		sprintf(buf,"N:服务器正在升级请稍后");
		return;
	}
	sprintf(buf,"Y:开户成功,卡号:%s 密码:%s",acc->bank,acc->pass);
	puts("开户成功");
	bank_id++;
	write(fd,acc,sizeof(Account));
	close(fd);
}
//登录
void login(Account * acc,char * buf)
{
	puts("用户正在登录");
	char path[256] = {};
	sprintf(path,"acc/%s",acc->bank);
	// 判断银行卡号是否正确
	if(0 != access(path,F_OK))
	{
		sprintf(buf,"N:卡号不存在,请检查!");
		return;
	}
	
	int fd = open(path,O_RDWR);
	if(0 > fd)
	{
		error("open");
		sprintf(buf,"N:服务器正在升级,登陆失败!");
		return;
	}
	//读取文件内容
	Account bcc = {};
	read(fd,&bcc,sizeof(Account));
	
	//判断此帐号是否被锁定
	if(bcc.islock >= 3)
	{
		sprintf(buf,"N:此账号已经锁定,请解锁!");
		return;
	}
	
	if(strcmp(acc->pass,bcc.pass))
	{
		bcc.islock++;
		sprintf(buf,"N:密码错误,重新登陆(您还有%d次机会)!",3-bcc.islock);
		if(bcc.islock >= 3)
		{
			sprintf(buf,"N:此账号已经锁定,请解锁!");
		}
	}
	else
	{
		bcc.islock = 0;
		sprintf(buf,"Y:恭喜您登陆成功!");
		puts("登陆成功");
	}
	lseek(fd,0,SEEK_SET);
	write(fd,&bcc,sizeof(Account));
	close(fd);
}
//销户
void destory(Account * acc,char * buf)
{
	puts("正在销户");
	char path[256] = {};
	sprintf(path,"acc/%s",acc->bank);
	// 判断银行卡号是否正确
	if(0 != access(path,F_OK))
	{
		puts("此卡号不存在");
		sprintf(buf,"N:卡号不存在,请检查!");
		return;
	}
	
	int fd = open(path,O_RDWR);
	if(0 > fd)
	{
		error("open");
		sprintf(buf,"N:服务器正在升级,销户失败");
		return;
	}
	
	Account bcc = {};
	read(fd,&bcc,sizeof(Account));
	close(fd);
	
	if(strcmp(bcc.card,acc->card))
	{
		sprintf(buf,"N:身份证号不正确,销户失败!");
		return;
	}
	
	if(strcmp(bcc.pass,acc->pass))
	{
		sprintf(buf,"N:密码不正确,销户失败!");
		return;
	}
	
	if(remove(path))
	{
		error("remove");
		sprintf(buf,"N:服务器正在升级,销户失败!");
		return;
	}
	puts("销户成功");
	sprintf(buf,"Y:销户成功,期待下次与你相遇!");
}
//解锁
void unlock(Account * acc,char * buf)
{
	puts("正在解锁");
	char path[256] = {};
	sprintf(path,"acc/%s",acc->bank);
	// 判断银行卡号是否正确
	if(0 != access(path,F_OK))
	{
		sprintf(buf,"N:卡号不存在,请检查!");
		return;
	}
	
	int fd = open(path,O_RDWR);
	if(0 > fd)
	{
		error("open");
		sprintf(buf,"N:服务器正在升级,解锁失败!");
		return;
	}
	
	Account bcc = {};
	read(fd,&bcc,sizeof(Account));
	if(strcmp(bcc.card,acc->card))
	{
		sprintf(buf,"N:身份证号不正确,解锁失败!");
		return;
	}
	
	if(strcmp(bcc.pass,acc->pass))
	{
		sprintf(buf,"N:密码不正确,解锁失败!");
		return;
	}
	
	bcc.islock = 0;
	lseek(fd,0,SEEK_SET);
	write(fd,&bcc,sizeof(Account));
	close(fd);
	puts("解锁成功");
	sprintf(buf,"N:解锁成功!");
}

//存款
void save(Account* acc,char* buf)
{
	puts("正在存款");
	char path[256] = {};
	sprintf(path,"acc/%s",acc->bank);
	
	int fd = open(path,O_RDWR);
	if(0 > fd)
	{
		error("open");
		sprintf(buf,"N:服务器正在升级,存款失败!");
		return;
	}
	
	Account bcc = {};
	read(fd,&bcc,sizeof(Account));

	bcc.balance += acc->balance;
	lseek(fd,0,SEEK_SET);
	write(fd,&bcc,sizeof(Account));
	close(fd);
	puts("存款成功");
	sprintf(buf,"N:存款成功,当前余额为:%g!",bcc.balance);
}

//取款
void take(Account* acc,char * buf)
{
	puts("正在取款");
	char path[256] = {};
	sprintf(path,"acc/%s",acc->bank);
	
	int fd = open(path,O_RDWR);
	if(0 > fd)
	{
		error("open");
		sprintf(buf,"N:服务器正在升级,取款失败!");
		return;
	}
	
	Account bcc = {};
	read(fd,&bcc,sizeof(Account));

	if(bcc.balance <  acc->balance)
	{
		sprintf(buf,"N:余额不足,取款失败。当前余额为:%g!",bcc.balance);
		return;
	}

	bcc.balance -= acc->balance;
	lseek(fd,0,SEEK_SET);
	write(fd,&bcc,sizeof(Account));
	close(fd);
	puts("取款成功");
	sprintf(buf,"N:取款成功,当前余额为:%g!",bcc.balance);
}
//转账
void transfer(Account* acc,char* buf)
{
	puts("正在转帐");
	char src_path[256] = {} , dest_path[256];
	
	sprintf(src_path,"acc/%s",acc->bank);
	sprintf(dest_path,"acc/%s",acc->card);
	
	// 判断银行卡号是否正确
	if(0 != access(dest_path,F_OK))
	{
		sprintf(buf,"N:目标卡号不存在,请检查!");
		return;
	}
	
	int src_fd = open(src_path,O_RDWR);
	int dest_fd = open(dest_path,O_RDWR);
	if(0 > src_fd || 0 > dest_fd)
	{
		error("open");
		sprintf(buf,"N:服务器正在升级,转账失败");
		return;
	}
	
	
	
	Account src_acc = {} , dest_acc = {};
	read(src_fd,&src_acc,sizeof(Account));
	read(dest_fd,&dest_acc,sizeof(Account));
	if( 0 ==strcmp(acc->bank,src_acc.bank))
	{
		sprintf(buf,"N:卡号不能相同");
		return ;
	}
	if(src_acc.balance <  acc->balance)
	{
		sprintf(buf,"N:余额不足,转账失败。当前余额为:%g!",src_acc.balance);
		return;
	}

	src_acc.balance -= acc->balance;
	dest_acc.balance += acc->balance;
	
	
	lseek(src_fd,0,SEEK_SET);
	lseek(dest_fd,0,SEEK_SET);
	write(src_fd,&src_acc,sizeof(Account));
	write(dest_fd,&dest_acc,sizeof(Account));
	close(src_fd);
	close(dest_fd);
	puts("转帐成功");
	sprintf(buf,"Y:转账成功,当前余额为:%g!",src_acc.balance);
}

//改密码
void repass(Account* acc,char* buf)
{
	puts("正在改密");
	char path[256] = {};
	sprintf(path,"acc/%s",acc->bank);
	if(0==strcmp(acc->pass,"-1"))
	{
		sprintf(buf,"N:两次输入的密码不相同,修改失败!");
		return ;
	}
	if(0==strcmp(acc->pass,"-2"))
	{
		sprintf(buf,"N:输入的密码和原来相同,修改失败!");
		return ;
	}
	int fd = open(path,O_WRONLY);
	if(0 > fd)
	{
		error("open");
		sprintf(buf,"N:服务器正在升级,查询失败!");
		return;
	}
	
	Account acc2 = {};
	read(fd,&acc2,sizeof(Account));
	
	strcpy(acc2.pass,acc->pass);
	printf("新密码:%s\n",acc2.pass);
	//fd = open(path,O_RDWR|O_TRUNC,0644);
	//write(fd,&acc2,sizeof(Account));
	acc2.balance+=acc->balance;
	close(fd);
	sprintf(buf,"N:修改密码成功!");
}
//查询
void query(Account* acc,char* buf)
{
	char path[256] = {};
	sprintf(path,"acc/%s",acc->bank);
	
	int fd = open(path,O_RDONLY);
	if(0 > fd)
	{
		error("open");
		sprintf(buf,"N:服务器正在升级,查询失败!");
		return;
	}
	
	Account bcc = {};
	read(fd,&bcc,sizeof(Account));
	close(fd);
	
	sprintf(buf,"N:查询成功,当前余额为:%g!",bcc.balance);
}


int main()
{
	signal(SIGINT,sigint);
	//printf("创建socket对象...\n");
	svr_fd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > svr_fd)
	{
		perror("socket");
		return -1;
	}
	
	//准备通信地址(自己)
	//printf("准备通信地址...\n");
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(6789);
	addr.sin_addr.s_addr = inet_addr("10.0.2.15");
	socklen_t addrlen = sizeof(addr);
	
	//绑定socket对象与地址
	//printf("绑定socket对象与地址...\n");
	if(bind(svr_fd,(struct sockaddr*)&addr,addrlen))
	{
		perror("bind");
		return -1;
	}
	
	//设置监听和排除数量
	//printf("设置监听");
	if(listen(svr_fd,10))
	{
		perror("listen");
		return -1;
	}
	puts("连接成功接受就绪");
	for(;;)
	{
		int cli_fd = accept(svr_fd,(struct sockaddr*)&addr,&addrlen);
		if(0 > cli_fd)
		{
			perror("accept");
			return -1;
		}
		pthread_t tid;
		pthread_create(&tid,NULL,server,&cli_fd);
	}
}

已知明显的BUG:服务端关闭后再开启后必须删除原有账号信息 有空再改

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值