银行管理系统

Linux系统项目之银行管理系统

系统简介

在之前写的博客里面提到了上一个项目简易聊天室的问题,在这个银行管理系统上面得到了解决,通过服务器的链表将用户输入的账号密码储存起来,然后在服务器不退出的情况下,实现用户的查询、存钱、取钱、转账、改密码、销户等功能,并将其交易记录写入了Mysql的数据库中。服务器即使退出,丢失账号密码但是交易记录还在。其实账号密码也是应当存储在数据库中,这样账户密码也不会丢失,但是为了练习链表将其写在了链表中。
下面写的是安装MySQL的数据库的命令。

apt-get install mysql-server //需要自己指定密码
apt-get install mysql-client
apt-get install libmysqlclient-dev//支持C语言API

客户端

客户端我通过设置termios结构体中的c_lflag设置来关闭回显,保证密码安全,通过查找资料封装了一个函数来管理是否回显。

/*************************************************************************
  > 文件路径: client.c
  > 作者: Moliam
  > 邮箱: 2515826079@qq.com 
  > 文件创建时间: 2019年03月20日 星期三 14时47分52秒
 ************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <termios.h>
#include <errno.h>//由于我修改了vim的配置,所以会出现没有必要的头文件

#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL)//回显相关宏定义
#define PORT 9709

int sockfd;
int text_fd;
//char *IP = "192.168.1.190";
char *IP = "192.168.15.2";//服务器IP地址

typedef struct sockaddr AD;
char acc[30]={0};//存放账户
char cmd_buf[30]={0};//存放命令
char dat_buf[100]={0};//存放数据

int set_disp_mode(int fd,int option);//是否回显函数
int getpasswd(char* passwd, int size);//获取终端输入函数
void err(const char *buf,int line);//出错函数
void Init(void);//初始化客户端
void Service(void);//匹配帐号密码
void menu(void);//菜单
void enquiry(void);//查询余额
void save(void);//存钱
void withdraw(void);//取钱
void modpw(void);//改密
void trans(void);//转账
void logout(void);//注销
void __exit(void);

int main(void)
{
	Init();
	Service();
	menu();//
	return 0;
}
void menu(void)
{
	//0查询 1存款 2取款 3转账 4改密 5销户 6退出
	int opt=0;
	while(1)
	{
		printf("*********************************\n");
		printf("              按0查询            \n");
		printf("              按1存款            \n");
		printf("              按2取款            \n");
		printf("              按3转账            \n");
		printf("              按4改密            \n");
		printf("              按5销户            \n");
		printf("              按6退出            \n");
		printf("*********************************\n");
repeat:		printf("请输入你需要进行的操作:\n");
		scanf("%d",&opt);
		if (opt > 6 && opt < 0)
		{
			printf("输入错误,请重新输入!\n");
			goto repeat;
		}
		switch(opt)
		{
			case 0:enquiry();break;
			case 1:save();break;
			case 2:withdraw();break;
			case 3:trans();break;
			case 4:modpw();break;
			case 5:logout();break;
			case 6:__exit();return ;
		}
	}
}
void enquiry(void)
{
	sprintf(cmd_buf,"0");
	text_fd = send(sockfd,cmd_buf,strlen(cmd_buf),0);//发送命令
	if(text_fd == -1)
		err("send",__LINE__);
	text_fd = recv(sockfd,dat_buf,sizeof(dat_buf),0);//接受余额
	if(text_fd == -1)
		err("recv",__LINE__);
	printf("当前余额为%s\n",dat_buf);
	memset(dat_buf,0,sizeof(dat_buf));
}
void save(void)
{
	double money = 0;
	sprintf(cmd_buf,"1");
	text_fd = send(sockfd,cmd_buf,strlen(cmd_buf),0);//发送命令
	if(text_fd == -1)
		err("send",__LINE__);
	printf("请输入你要存的数目:\n");
	scanf("%lf",&money);
	sprintf(dat_buf,"%.2f",money);
	text_fd = send(sockfd,dat_buf,strlen(dat_buf),0);//发送数目
	if(text_fd == -1)
		err("send",__LINE__);
	memset(dat_buf,0,sizeof(dat_buf));
	text_fd = recv(sockfd,dat_buf,sizeof(dat_buf),0);//接收是否成功
	if(text_fd == -1)
		err("recv",__LINE__);
	if(strcmp(dat_buf,"correct") != 0)
	{
		printf("aha,failure!\n");
	}
	memset(dat_buf,0,sizeof(dat_buf));
	enquiry();
}
void withdraw(void)
{
	float money = 0;
	sprintf(cmd_buf,"2");
	text_fd = send(sockfd,cmd_buf,strlen(cmd_buf),0);//发送命令
	if(text_fd == -1)
		err("send",__LINE__);
	printf("请输入你要提现的数目:\n");
	scanf("%f",&money);
	sprintf(dat_buf,"%.2f",money);
	text_fd = send(sockfd,dat_buf,strlen(dat_buf),0);//发送数目
	if(text_fd == -1)
		err("send",__LINE__);
	memset(dat_buf,0,sizeof(dat_buf));
	text_fd = recv(sockfd,dat_buf,sizeof(dat_buf),0);//接收是否成功
	if(text_fd == -1)
		err("recv",__LINE__);
	if(strcmp(dat_buf,"correct") != 0)
	{
		printf("aha,failure!\n");
	}
	memset(dat_buf,0,sizeof(dat_buf));
	enquiry();
}
void trans(void)
{
	float money = 0;
	char name[20];
	sprintf(cmd_buf,"3");
	text_fd = send(sockfd,cmd_buf,strlen(cmd_buf),0);//发送命令
err:	memset(name,0,sizeof(name));
	if(text_fd == -1)
		err("send",__LINE__);
	printf("请输入你要转账的账户(按quit退出):\n");
	scanf("%s",name);
	getchar();
	if(strcmp(name,"quit") == 0)
		{text_fd = send(sockfd,name,strlen(name),0);return;}
	text_fd = send(sockfd,name,strlen(name),0);//发送名字
	if(text_fd == -1)
		err("send",__LINE__);
	memset(dat_buf,0,sizeof(dat_buf));
	text_fd = recv(sockfd,dat_buf,sizeof(dat_buf),0);//接收是否存在
	if(text_fd == -1)
		err("recv",__LINE__);
	if(strcmp(dat_buf,"correct") != 0)
	{
		printf("aha,failure!Not such the person!\n");
		goto err;
	}
	memset(dat_buf,0,sizeof(dat_buf));
	scanf("%f",&money);
	sprintf(dat_buf,"%.2f",money);
	text_fd = send(sockfd,dat_buf,strlen(dat_buf),0);//发送数目
	if(text_fd == -1)
		err("send",__LINE__);
	text_fd = recv(sockfd,dat_buf,sizeof(dat_buf),0);//接收是否成功
	if(text_fd == -1)
		err("recv",__LINE__);
	if(strcmp(dat_buf,"correct") != 0)
	{
		printf("aha,failure!You have no money!\n");
	}
	memset(dat_buf,0,sizeof(dat_buf));
	enquiry();
}
void modpw(void)
{
	char *p,passwd[20],com[20];
	sprintf(cmd_buf,"4");
	text_fd = send(sockfd,cmd_buf,strlen(cmd_buf),0);//发送命令
	if(text_fd == -1)
		err("send",__LINE__);
	set_disp_mode(STDIN_FILENO,0);//关闭回显
	getchar();
	getpasswd(passwd, sizeof(passwd));
	p=passwd;
	while(*p!='\n')
		p++;
	*p='\0';
	printf("\n");
	getpasswd(com, sizeof(com));
	p=com;
	while(*p!='\n')
		p++;
	*p='\0';
	printf("\n");
	set_disp_mode(STDIN_FILENO,1);//打开回显
	if(strcmp(passwd,com) != 0)
	{	
		printf("两次输入密码不一致!!\n");
		return ;
	}
	text_fd = send(sockfd,passwd,strlen(passwd),0);//发送密码
	if(text_fd == -1)
		err("send",__LINE__);
	text_fd = recv(sockfd,dat_buf,sizeof(dat_buf),0);//接收是否成功
	if(text_fd == -1)
		err("recv",__LINE__);
	if(strcmp(dat_buf,"correct") != 0)
	{
		printf("aha,failure!\n");
	}
	memset(dat_buf,0,sizeof(dat_buf));
}
void logout(void)
{
	sprintf(cmd_buf,"5");
	text_fd = send(sockfd,cmd_buf,strlen(cmd_buf),0);//发送命令
	if(text_fd == -1)
		err("send",__LINE__);
	text_fd = recv(sockfd,dat_buf,sizeof(dat_buf),0);//接收是否成功
	if(text_fd == -1)
		err("recv",__LINE__);
	if(strcmp(dat_buf,"correct") != 0)
	{
		printf("aha,failure!\n");
	}
	memset(dat_buf,0,sizeof(dat_buf));
	exit(-1);
}
void __exit(void)
{
	sprintf(cmd_buf,"6");
	text_fd = send(sockfd,cmd_buf,strlen(cmd_buf),0);//发送命令
	if(text_fd == -1)
		err("send",__LINE__);
	exit(-1);
}

void Service(void)
{
	char *p,passwd[20];
err:
	printf("请输入你的帐号(无该帐号自动注册):");
	scanf("%s",acc);
	getchar();//读走回车
	if(strcmp(acc,"quit") == 0)//为了防止误操作进入转账页面
	{
		printf("创建失败,账户已存在\n");
		goto err;
	}
	set_disp_mode(STDIN_FILENO,0);
	getpasswd(passwd, sizeof(passwd));
	p=passwd;
	while(*p!='\n')
		p++;
	*p='\0';
	set_disp_mode(STDIN_FILENO,1);
	text_fd = send(sockfd,acc,strlen(acc),0);
	if(text_fd == -1)
		err("send",__LINE__);
	sleep(1);
	text_fd = send(sockfd,passwd,strlen(passwd),0);
	if(text_fd == -1)
		err("send",__LINE__);
	char mod_buf[20];
	memset(mod_buf,0,sizeof(mod_buf));
	text_fd = recv(sockfd,mod_buf,sizeof(mod_buf),0);
	if(text_fd == -1)
		err("recv",__LINE__);
	printf("%s\n",mod_buf);
	if(strcmp(mod_buf,"correct") != 0)
	{
		printf("帐号密码输入错误,请重新输入!\n");
		goto err;
	}
}
void Init(void)
{
	sockfd = socket(PF_INET,SOCK_STREAM,0);
	if(sockfd == -1)
		err("socket",__LINE__);
	struct sockaddr_in addr;
	addr.sin_family = PF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = inet_addr(IP);
	if(connect(sockfd,(AD*)&addr,sizeof(addr)) == -1)
		err("connect",__LINE__);
	printf("客户端初始化成功!\n");
}

void err(const char *buf,int line)
{
	fprintf(stderr,"出错行号是%d\n",line);
	perror(buf);
	exit(-1);
}
//函数set_disp_mode用于控制是否开启输入回显功能  
//如果option为0,则关闭回显,为1则打开回显  
int set_disp_mode(int fd,int option)
{  
	int err;  
	struct termios term;  
	if(tcgetattr(fd,&term)==-1)
	{
		perror("不能获得终端属性!\n");  
		return 1;  
	}  
	if(option)  
		term.c_lflag|=ECHOFLAGS;  
	else  
        	term.c_lflag &=~ECHOFLAGS;  
	err=tcsetattr(fd,TCSAFLUSH,&term);  
	if(err==-1 && err==EINTR)
	{  
		perror("不能设置终端属性!\n");  
		return 1;  
	}  
	return 0;  
}
int getpasswd(char* passwd, int size)//获得密码函数
{
	int c;
	int n = 0;
	printf("请输入密码:");
	do
	{
		c=getchar();
		if (c != '\n'|c!='\r')
		{
			passwd[n++] = c;
		}
	}while(c != '\n' && c !='\r' && n < (size - 1));//当读到回车,换行或者超出了
	passwd[n] = '\0';
	return n;
}

服务器

服务器通过链表来存储账号密码,然后将交易记录放在了数据库中,因为我建立的数据库名字时band_msg,数据库的建立顺序应先于服务器执行代码,不然会出现链接数据库错误的问题

/*************************************************************************
  > 文件路径: service.c
  > 作者: Moliam
  > 邮箱: 2515826079@qq.com 
  > 文件创建时间: 2019年03月20日 星期三 14时47分43秒
 ************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <mysql/mysql.h>
#include <errno.h>

#define MAX_CLI 256
#define PORT 9709
int sockfd;
int text_fd;
//char *IP = "192.168.1.190";
char *IP = "192.168.15.2";


struct DAT//数据块,存放账户密码
{
	char acc[30];
	char pwd[20];
};

typedef struct DAT date;

struct client 
{
	date dat;
	struct client *next;
};

typedef struct sockaddr AD;//类型定义
typedef struct client CLI;

CLI *head = NULL;//链表头
CLI *pnew = NULL;//指向下一个链表
CLI *tmp = NULL;//临时指针

int create_head(void);//创建链表头
void Init(void);//初始化TCP
void err(const char *buf,int line);//错误信息打印并退出
void Service(void);//等待客户函数
void *service_thread(void* p);//客户端服务函数
float enquiry(int fd,char *acc_buf,MYSQL sql,int flag);//查询余额
void save(int fd,char *acc_buf,MYSQL sql);//存钱
void withdraw(int fd,char *acc_buf,MYSQL sql);//取钱
void modpw(int fd,char *acc_buf,MYSQL sql);//改密
void trans(int fd,char *acc_buf,MYSQL sql);//转账
void logout(char *buf,MYSQL sql);//注销

int main(void)
{
	create_head();
	Init();
	Service();
	return 0;
}

void Service(void)
{
	while(1)
	{
		struct sockaddr_in fromaddr;
		int len = sizeof(fromaddr);
		int fd ;
acc:		
		fd = accept(sockfd,(AD*)&fromaddr,&len);
		if(fd == -1)
		{	//err("accept",__LINE__);
			printf("CONNECT ERROR!\n");
			goto acc;
		}
		pthread_t id;
		pthread_create(&id,0,service_thread,&fd);//有一个客户端即将建立连接时分配一个线程
		tmp = head->next;
	}
}
void *service_thread(void* p)
{
	int fd = *(int *)p;
	int option;
	char acc_buf[30],pwd_buf[20],dat_buf[30];
	MYSQL my_sql;
	//初始化结构体
	mysql_init(&my_sql);
	//连接mysql数据库band_msg
	if(mysql_real_connect(&my_sql,"localhost","root","1","band_msg",0,NULL,0)==NULL)
	{
		perror("mysql_real_connect");
		return (void *)-1;
	}
err:	memset(acc_buf,0,sizeof(acc_buf));
	text_fd = recv(fd,acc_buf,sizeof(acc_buf),0);
	if(text_fd == -1)
		err("recv",__LINE__);
	memset(pwd_buf,0,sizeof(pwd_buf));
	text_fd = recv(fd,pwd_buf,sizeof(pwd_buf),0);
	if(text_fd == -1)
		err("recv",__LINE__);
	tmp = head->next;
	while(tmp != NULL)//若链表中能够找到该帐号
	{
		if (strcmp(acc_buf,tmp->dat.acc) == 0)
		{
			if(strcmp(pwd_buf,tmp->dat.pwd) == 0)
			{
				char *cor_buf = "correct";
				text_fd = send(fd,cor_buf,strlen(cor_buf),0);
				goto cor;//帐号密码输入正确
			}
			else
			{
				char *err_buf = "error";
				text_fd = send(fd,err_buf,strlen(err_buf),0);
				goto err;
			}
		}
		tmp = tmp -> next;
	}
	char *cor_buf = "correct";
	text_fd = send(fd,cor_buf,strlen(cor_buf),0);
	//没有找到,自动注册,在链表尾新建一个链表
	pnew = (CLI *)malloc(sizeof(CLI));
	pnew->next = NULL;
	strcpy(pnew->dat.acc,acc_buf);
	strcpy(pnew->dat.pwd,pwd_buf);
	tmp=head;//确保加在了链表尾
	while(tmp->next!=NULL)
	{
		tmp=tmp->next;
	}
	tmp->next = pnew;
	//为该客户创建数据表(time change balance)
	//为新用户创建表
	char cli_buf[200];
	memset(cli_buf,0,sizeof(cli_buf));
	sprintf(cli_buf,"create table %s(time int(8),exchange decimal(10,2),balance decimal(12,2))",acc_buf);
	//这里尽量不要用float因为float会出现一些小数计算失误,虽然我并没有用数据库的计算,时间为time函数得出来的数值,也可以改变为varchar型,
	//然后用asctime函数得到时间字符串
	//这里的exchange设置的(10,2),也代表了一次交易最大99999999.99,需要该上限的话可以改一下,后面的余额也一样
	if((mysql_real_query(&my_sql,cli_buf,strlen(cli_buf)))!=0)
	{
		perror("mysql_real_query");
		return (void *)-1;
	}
	//给新用户余额赋值为0
	sprintf(cli_buf,"insert into %s(time,exchange,balance)values(%ld,0,0)",acc_buf,time(NULL));
	if((mysql_real_query(&my_sql,cli_buf,strlen(cli_buf)))!=0)
	{
		perror("mysql_real_query");
		return (void *)-1;
	}
cor:	
	option = 0;
	while(1)
	{
		MYSQL my_sql;
		//初始化结构体
		mysql_init(&my_sql);
		//连接mysql数据库band_mes
		if(mysql_real_connect(&my_sql,"localhost","root","xxxxx","band_msg",0,NULL,0)==NULL)//链接数据库
		{
			perror("mysql_real_connect");
			return (void *)-1;
		}
		text_fd = recv(fd,dat_buf,sizeof(dat_buf),0);
		if(text_fd == -1)
			err("recv",__LINE__);
		option = atoi(dat_buf);//将接收到的命令转换为整型,因为传来的是字符串
		//0查询 1存款 2取款 3转账 4改密 5销户 6退出
		switch(option)
		{
			case 0:enquiry(fd,acc_buf,my_sql,1);break;
			case 1:save(fd,acc_buf,my_sql);break;
			case 2:withdraw(fd,acc_buf,my_sql);break;
			case 3:trans(fd,acc_buf,my_sql);break;
			case 4:modpw(fd,acc_buf,my_sql);break;
			case 5:logout(acc_buf,my_sql);break;
			case 6:mysql_close(&my_sql);pthread_exit((void *)1);
		}
	}
}
float enquiry(int fd,char *acc_buf,MYSQL sql,int flag)//flag为标志位,表示给不给客户端发送余额,如果发送接收对应不齐会出现bug
{
	//查询余额并发送
	//select balance from tablename order by time desc limit 1选取最新一次的数据的余额
	char buf[100],money[100];
	memset(buf,0,sizeof(buf));
	memset(money,0,sizeof(money));
	sprintf(buf,"select balance from %s order by time desc limit 1",acc_buf);//这里获得的结果集就是最后一次的交易余额,只有一行一列
	if((mysql_real_query(&sql,buf,strlen(buf))) != 0)
		err("mysql_real_query",__LINE__);
	MYSQL_RES *p=NULL;//获取到的数据库结果存放在了该结构体中
	p = mysql_store_result(&sql);
	if(p == NULL)
		err("mysql_store_result",__LINE__);
	int col = mysql_num_fields(p);
	int row = mysql_num_rows(p);
	MYSQL_ROW dat;
	unsigned int i;
	while((dat = mysql_fetch_row(p)))//在MySQL官网找的程序,可以循环得到结果集,我只选取了一行一列
	{
		unsigned long *lengths;
		lengths = mysql_fetch_lengths(p);
		for(i = 0;i< col;i++)
		{
			sprintf(money,"%.*s",(int)lengths[i],dat[i]?dat[i]:"NULL");
			if(flag == 1)
				text_fd = send(fd,money,strlen(money),0);
			return atof(money);
		}
	}
	mysql_free_result(p);//使用完结果集之后必须释放掉其内存空间
	return -1;
}
void save(int fd,char *acc_buf,MYSQL sql)
{
	//接收存钱的数目
	//发送成功或者失败
	char buf[100],money[100];
	float saving,balance;
	memset(buf,0,sizeof(buf));
	memset(money,0,sizeof(money));
	balance = enquiry(fd,acc_buf,sql,0);
	text_fd = recv(fd,money,sizeof(money),0);
	if(text_fd == -1)
		err("recv",__LINE__);
	saving = atof(money);//字符型转换为浮点型
	sprintf(buf,"insert into %s(time,exchange,balance)values(%ld,%f,%f)",acc_buf,time(NULL),saving,balance+saving);
	if((mysql_real_query(&sql,buf,strlen(buf)))!=0)
	{
		perror("mysql_real_query");
		return ;
	}
	text_fd = send(fd,"correct",strlen("correct"),0);
	return ;
}
void withdraw(int fd,char *acc_buf,MYSQL sql)
{
	//接收取款的数目
	//发送成功或者失败
	char buf[100],money[100];
	float wd,balance;
	memset(buf,0,sizeof(buf));
	memset(money,0,sizeof(money));
	balance = enquiry(fd,acc_buf,sql,0);
	text_fd = recv(fd,money,sizeof(money),0);
	if(text_fd == -1)
		err("recv",__LINE__);
	wd = atof(money);
	if(balance < wd)
	{text_fd = send(fd,"error",strlen("error"),0);return;}
	sprintf(buf,"insert into %s(time,exchange,balance)values(%ld,%f,%f)",acc_buf,time(NULL),wd,balance-wd);
	if((mysql_real_query(&sql,buf,strlen(buf)))!=0)
	{
		perror("mysql_real_query");
		return ;
	}
	text_fd = send(fd,"correct",strlen("correct"),0);
}
void trans(int fd,char *acc_buf,MYSQL sql)
{
	//接受名字
	//发送是否存在
	//接受数目
	//发送是否成功
	int exist=0;
	float tran,balance1,balance2;
	char name[20],money[100],dat_buf[130];
err:	memset(name,0,sizeof(name));
	memset(money,0,sizeof(money));
	memset(dat_buf,0,sizeof(dat_buf));
	text_fd = recv(fd,name,sizeof(name),0);
	if(text_fd == -1)
		err("recv",__LINE__);
	if(strcmp(name,"quit") == 0)
		return;
	tmp = head->next;
	while(tmp != NULL)//若链表中能够找到该帐号
	{
		if (strcmp(name,tmp->dat.acc) == 0)
			exist = 1; 
		tmp = tmp -> next;
	}
	if(exist == 0)
		{text_fd = send(fd,"error",strlen("error"),0);goto err;}
	else
		text_fd = send(fd,"correct",strlen("correct"),0);
	text_fd = recv(fd,money,sizeof(money),0);
	if(text_fd == -1)
		err("recv",__LINE__);
	tran = atof(money);
	balance1 = enquiry(fd,name,sql,0);//得到两人余额并进行计算
	balance2 = enquiry(fd,acc_buf,sql,0);
	sprintf(dat_buf,"insert into %s(time,exchange,balance)values(%ld,%f,%f)",name,time(NULL),tran,balance1+tran);
	if((mysql_real_query(&sql,dat_buf,strlen(dat_buf)))!=0)
	{
		perror("mysql_real_query");
		return ;
	}
	memset(dat_buf,0,sizeof(dat_buf));
	sprintf(dat_buf,"insert into %s(time,exchange,balance)values(%ld,%f,%f)",acc_buf,time(NULL),tran,balance2-tran);
	if((mysql_real_query(&sql,dat_buf,strlen(dat_buf)))!=0)
	{
		perror("mysql_real_query");
		return ;
	}
	text_fd = send(fd,"correct",strlen("correct"),0);
}
void modpw(int fd,char *acc_buf,MYSQL sql)
{
	//接受密码
	//发送是否成功
	char pw[100];
	memset(pw,0,sizeof(pw));
	text_fd = recv(fd,pw,sizeof(pw),0);
	if(text_fd == -1)
		err("recv",__LINE__);
	tmp = head->next;
	while(tmp != NULL)//若链表中能够找到该帐号
	{
		if (strcmp(acc_buf,tmp->dat.acc) == 0)
		{
			strcpy(tmp->dat.pwd,pw);
		}
		tmp = tmp -> next;
	}
	text_fd = send(fd,"correct",strlen("correct"),0);
}
void logout(char *buf,MYSQL sql)
{
	CLI * tmp1 = NULL;
	CLI * tmp2 = NULL;
	tmp2=head;
	tmp1=head->next;
	while(tmp1 != NULL)//找到该帐号
	{
		if (strcmp(buf,tmp1->dat.acc) == 0)
		{
			tmp2->next = tmp1->next;
			free(tmp1);
			return ;
		}
		tmp2 = tmp2->next;
		tmp1 = tmp1->next;
	}
	char drop_buf[150];
	sprintf(drop_buf,"drop table %s",buf);//删除其数据库
	if((mysql_real_query(&sql,drop_buf,strlen(drop_buf)))!=0)
	{
		perror("mysql_real_query");
		return ;
	}
}
int create_head(void)
{
	head = (CLI *)malloc(sizeof(CLI));
	if(head == NULL)
		err("CREATE FAILURE!",__LINE__);
	else 
		head->next = NULL;
	return 1;
}
//TCP协议前面的步骤初始化
void Init(void)
{
	sockfd = socket(PF_INET,SOCK_STREAM,0);//IPV4
	if(sockfd == -1)
		err("socket",__LINE__);
	struct sockaddr_in addr;
	addr.sin_family = PF_INET;
	addr.sin_port = htons(PORT);//端口号
	addr.sin_addr.s_addr = inet_addr(IP);//服务器为本机
	if(bind(sockfd,(AD *)&addr,sizeof(addr)) == -1)
		err("bind",__LINE__);
	if(listen(sockfd,MAX_CLI) == -1)
		err("listen",__LINE__);
	printf("服务器初始化成功\n");
}
void err(const char *buf,int line)
{
	fprintf(stderr,"出错行号是%d\n",line);
	perror(buf);
	exit(-1);
}

makefile

v1:
	@gcc service.c -o s -lpthread -lmysqlclient
	@gcc client.c -o c -lpthread -lmysqlclient
clean:
	@rm s c a.out -rf
gedit:
	@gedit service.c client.c

总结

我写的简易聊天室和银行管理系统使用了许多相同的函数,因为之前写过比较方便嘛,思路也大体一致,只不过银行管理系统的功能更加完备一些,使用到的知识也相对多一些。

  • 14
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
----------------------- 计算机-数据库课程设计-银行管理系统全文共24页,当前为第1页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第2页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第3页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第4页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第5页。 帐号 银行 储户 开户地址 姓名 性别 帐户余额 开户日期 密码 身份证号 定期操作记录 活期操作记录 计算机-数据库课程设计-银行管理系统全文共24页,当前为第6页。 定期记录 存取款人姓名 操作日期 帐号 操作金额 年份 活期存取款 存储 帐号 银行 储户 开户地址 姓名 性别 帐户余额 开户日期 密码 身份证号 定期存取款 定期操作记录 活期操作记录 计算机-数据库课程设计-银行管理系统全文共24页,当前为第7页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第8页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第9页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第10页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第11页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第12页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第13页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第14页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第15页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第16页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第17页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第18页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第19页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第20页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第21页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第22页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第23页。 计算机-数据库课程设计-银行管理系统全文共24页,当前为第24页。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值