项目名称:模拟ATM 存取款机
编程语言:C语言
开发环境:linux
项目功能:
(1) 用户注册登录
(2) 登录成功之后可以进行查询余额,存款,取款,销户
项目实现:
(1) 客户端和服务器端之间使用tcp通信
(2) 服务器端采用IO多路复用并发服务器
(3) 客户端给服务器端发送消息,服务器端对收到的消息进行解析之后执行对应的操作,并操作数据库
代码:
一:客户端:
结构体定义:
typedef struct atm
{
char name[20];
char num[20];
char id[20];
char passwd[20];;
char money[20];
}Atm;
各项功能的菜单函数
void menu()
{
printf("*****************************\n");
printf("\n");
printf("\t\t1.注册\n");
printf("\t\t2.登陆\n");
printf("\t\t3.退出\n");
printf("\n");
printf("*****************************\n");
}
void menu2()
{
printf("*****************************\n");
printf("\n");
printf("\t\t4.查询余额\n");
printf("\t\t5.存款\n");
printf("\t\t6.取款\n");
printf("\t\t7.销户\n");
printf("\t\t3.退出\n");
printf("\n");
printf("******************************\n");
}
客户端的主函数:
#include"net.h"
int main(int argc, char *argv[])
{
Atm a1;
memset(&a1,0,sizeof(a1));
//c创建套接字
int tcp_socket = tcp_client(argv[1],atoi(argv[2]));
if(tcp_socket < 0)
{
return -1;
}
char buf[100]={'\0'};
int op,ret,option=1;
while(1)
{
if(option < 2)
{
menu();
printf("请输入选项:\n");
scanf("%d",&op);
send(tcp_socket,&op,sizeof(op),0);
if(3 == op)
{
printf("退出成功!\n");
break;
}
switch(op)
{
case 1:
//注册
registe(tcp_socket);
break;
case 2:
//登陆
option=login(tcp_socket,&a1);
printf("id=%s,passwd=%s\n",a1.id,a1.passwd);
break;
}
}
else if(option == 2)
{
menu2();
printf("请输入选项:\n");
scanf("%d",&op);
send(tcp_socket,&op,sizeof(op),0);
if(3 == op)
{
printf("退出成功!\n");
break;
}
switch(op)
{
case 4:
//查询余额
inquire(tcp_socket,&a1);
break;
case 5:
//存款
save(tcp_socket,&a1);
break;
case 6:
//取款
take(tcp_socket,&a1);
break;
case 7:
//销户
option = delete1(tcp_socket,&a1);
break;
default:
printf("输入错误,请重新输入!\n");
}
}
}
close(tcp_socket);
return 0;
}
tcpt通信的搭建:
#include"net.h"
int tcp_client(char *ip,int port)
{
int tcp_socket = socket(AF_INET,SOCK_STREAM,0);
if(tcp_socket < 0)
{
perror("create error");
return -1;
}
printf("socket ok\n");
struct sockaddr_in server;
memset(&server,'\0',sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip);
if(connect(tcp_socket,(struct sockaddr *)&server,sizeof(server)) < 0)
{
perror("connect error");
return -1;
}
printf("connect ok\n");
//允许端口和地址复用
int on = 1;
setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
return tcp_socket;
}
注册:
//注册
void registe(int tcp_socket)
{
Atm a1={'\0'};
int ret;
char buf[100]={'\0'};
printf("请输入姓名:\n");
scanf("%s",a1.name);
printf("请输入身份证号:\n");
scanf("%s",a1.num);
printf("请输入想要设置的密码:\n");
scanf("%s",a1.passwd);
memset(buf,'\0',sizeof(buf));
sprintf(buf,"%s#%s#%s#%s#%s",a1.name,a1.num,a1.id,a1.passwd,a1.money);
send(tcp_socket,buf,sizeof(buf),0);
recv(tcp_socket,&ret,sizeof(ret),0);
if(0==ret)
{
printf("该身份证号已被注册\n");
}
else
{
printf("注册成功!卡号为:%d\n",ret);
}
}
登录:
//登陆
int login(int tcp_socket,Atm *a11)
{
int ret;
Atm a1 = {'\0'};
char buf[100]={'\0'};
printf("请输入卡号:");
scanf("%s",a1.id);
printf("请输入密码:\n");
scanf("%s",a1.passwd);
memset(buf,'\0',sizeof(buf));
sprintf(buf,"%s#%s",a1.id,a1.passwd);
send(tcp_socket,buf,sizeof(buf),0);
recv(tcp_socket,&ret,sizeof(ret),0);
if(-1==ret)
{
printf("该卡号未被注册\n");
return 1;
}
else if(ret == 0)
{
printf("密码输入错误!\n");
return 1;
}
else
{
*a11 = a1;
printf("登陆成功!\n");
return 2;
}
}
查询余额:
void inquire(int tcp_socket,Atm *a1)
{
int ret;
send(tcp_socket,a1->id,sizeof(a1->id),0);
recv(tcp_socket,&ret,sizeof(ret),0);
if(ret < 0)
{
printf("inquire error\n");
}
else
{
sprintf(a1->money,"%d",ret);
printf("%s\n",a1->money);
}
}
存款:
void save(int tcp_socket,Atm *a1)
{
int ret;
int save_money;
char pwd[100] = {'0'};
char pwd2[100] = {'0'};
sprintf(pwd2,"%s",a1->passwd);
memset(a1,0,sizeof(a1));
printf("请输入您要存入的金额:\n");
scanf("%d",&save_money);
printf("请输入您的密码:\n");
scanf("%s",pwd);
if(strcmp(pwd,pwd2)!=0){
printf("密码错误!\n");
return;
}
send(tcp_socket,&save_money,sizeof(save_money),0);
send(tcp_socket,a1->id,sizeof(a1->id),0);
recv(tcp_socket,&ret,sizeof(ret),0);
if(ret > 0)
{
printf("存入成功!余额为:%d\n",ret);
}
else
{
printf("存入失败!\n");
}
}
取款:
void take(int tcp_socket,Atm *a1)
{
int ret;
int save_money;
char pwd[100] = {'0'};
char pwd2[100] = {'0'};
sprintf(pwd2,"%s",a1->passwd);
memset(a1,0,sizeof(a1));
printf("请输入您要取出的金额:\n");
scanf("%d",&save_money);
printf("请输入您的密码:\n");
scanf("%s",pwd);
if(strcmp(pwd,pwd2)!=0){
printf("密码错误!\n");
return;
}
send(tcp_socket,&save_money,sizeof(save_money),0);
send(tcp_socket,a1->id,sizeof(a1->id),0);
recv(tcp_socket,&ret,sizeof(ret),0);
if(ret >= 0)
{
printf("取出成功!余额为:%d\n",ret);
}
else if(ret==-1)
{
printf("存入失败!\n");
}else{
printf("余额不足!\n");
}
}
销户:
int delete1(int tcp_socket,Atm *a1)
{
int ret;
send(tcp_socket,a1->id,sizeof(a1->id),0);
recv(tcp_socket,&ret,sizeof(ret),0);
if(ret < 0)
{
printf("销户失败\n");
return 2;
}
else
{
printf("销户成功\n");
return 1;
}
}
二:服务器端
主函数:
#include"net.h"
int main(int argc, char *argv[])
{
//创建并打开数据库
sqlite3 *db;
if(sqlite3_open("user.db",&db) != SQLITE_OK)
{
printf("open error\n");
return -1;
}
printf("open ok\n");
//创建表
if(create_user(db) < 0)
{
return -1;
}
int listenfd=tcp_socket(argv[1],atoi(argv[2]));
if(listenfd < 0)
{
return -1;
}
fd_set rdfs,temp;
FD_ZERO(&rdfs);
FD_ZERO(&temp);
FD_SET(listenfd,&rdfs);
int newfd;
Atm a1;
int i;
while(1)
{
temp = rdfs;
if(select(FD_SETSIZE,&temp,NULL,NULL,NULL)<0)
{
perror("select error\n");
close(listenfd);
return -1;
}
for(i=0;i<FD_SETSIZE;i++)
{
if(FD_ISSET(i,&temp))
{
if(i == listenfd)
{
//监听是否有人介入
struct sockaddr_in user;
int len = sizeof(user);
newfd = accept(i,(struct sockaddr *)&user,&len);
if(newfd < 0)
{
return -1;
}
printf("有新用户连接\n");
printf("ip:%s port:%d\n",inet_ntoa(user.sin_addr),user.sin_port);
FD_SET(newfd,&rdfs);
}
else
{
//通信套接字
int op,option;
int value;
int ret = -1;
char *str[10]={'\0'};
char buf[100]={'\0'};
int n = recv(i,&op,sizeof(op),0);
printf("op = %d\n",op);
if(n < 0)
{
return -1;
}
else if(n==0)
{
//客户端退出
close(i);
FD_CLR(i,&rdfs);
continue;
}
else
{
if(op<=2)
{
switch(op)
{
case 1:
//注册
memset(buf,0,sizeof(buf));
recv(i,buf,sizeof(buf),0);
paseStr(buf,str);
ret = registe(db,str);
if(ret == 0)
{
value = 0;
continue;
}
else
{
send(i,&ret,sizeof(ret),0);
}
break;
case 2:
//登陆
memset(buf,0,sizeof(buf));
recv(i,buf,sizeof(buf),0);
paseStr(buf,str);
ret = login(db,str);
if(ret < 0)
{
send(i,&ret,sizeof(ret),0);
}
else if(ret == 0)
{
send(i,&ret,sizeof(ret),0);
}
else
{
//option = 2;
send(i,&ret,sizeof(ret),0);
}
break;
}
}
else if(op > 2)
{
if(3==op)
{
close(i);
FD_CLR(i,&rdfs);
continue;
}
int money;
switch(op)
{
case 4:
//查询余额
recv(i,buf,sizeof(buf),0);
ret = select1(db,buf);
if(ret < 0)
{
send(i,&ret,sizeof(ret),0);
}
else
{
send(i,&ret,sizeof(ret),0);
}
break;
case 5:
//存款
recv(i,&money,sizeof(money),0);
recv(i,buf,sizeof(buf),0);
ret = save(db,buf,money);
if(ret < 0)
{
send(i,&ret,sizeof(ret),0);
}
else
{
send(i,&ret,sizeof(ret),0);
}
break;
case 6:
//存款
recv(i,&money,sizeof(money),0);
recv(i,buf,sizeof(buf),0);
ret = take(db,buf,money);
if(ret < 0)
{
send(i,&ret,sizeof(ret),0);
}
else
{
send(i,&ret,sizeof(ret),0);
}
break;
case 7:
//销户
recv(i,buf,sizeof(buf),0);
ret = delete1(db,buf);
if(ret < 0)
{
send(i,&ret,sizeof(ret),0);
}
else
{
send(i,&ret,sizeof(ret),0);
}
break;
}
}
}
}
}
}
}
close(listenfd);
return 0;
}
tcp通信:
#include"net.h"
int tcp_socket(char *ip,int port)
{
int socket_fd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == socket_fd)
{
perror("socket error");
return -1;
}
printf("socket ok\n");
struct sockaddr_in server;
memset(&server,'\0',sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip);
int on=1;
setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
if(bind(socket_fd,(struct sockaddr *)&server,sizeof(server)) < 0)
{
perror("bind error");
return -1;
}
printf("bind ok\n");
if(listen(socket_fd,5) < 0)
{
perror("listen error");
return -1;
}
printf("listen ok\n");
return socket_fd;
}
解析函数:
void paseStr(char *buf,char *pstr[])
{
pstr[0]=buf;
int i=0,j=0;
while(buf[i]!='\0')
{
if('#' == buf[i])
{
j++;
buf[i]='\0';
pstr[j]=&buf[i+1];
}
i++;
}
}
表的创建:
int create_user(sqlite3 *db)
{
char *errmsg = NULL;
char sql[]="create table user (name text,num text,id text,passwd text,money text)";
int rc = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
if(rc != SQLITE_OK && rc != 1)
{
printf("create error:%s\nrc=%d\n",errmsg,rc);
sqlite3_free(errmsg);
return -1;
}
else
{
printf("create usertable ok\n");
return 0;
}
}
注册:
int registe(sqlite3 *db,char *str[])
{
char **result;
int nrow,ncolumn,i,j;
char sql[]="select max(id) from user";
sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,NULL);
int id = atoi(result[nrow])+1;
char sql2[100]={'\0'};
sprintf(sql2,"insert into user (name,num,id,passwd,money) values ('%s','%s','%d','%s','0')",str[0],str[1],id,str[3]);
if(sqlite3_exec(db,sql2,NULL,NULL,NULL))
{
return -1;
}
return id;
}
登录:
int login(sqlite3 *db,char *str[])
{
char **result;
int nrow,ncolumn,i,j;
char sql[100]={'\0'};
sprintf(sql,"select passwd from user where id = '%s'",str[0]);
sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,NULL);
if(nrow<=0)
return -1;
if(strcmp(result[nrow],str[1])!=0)
return 0;
return 1;
}
查询余额:
int select1(sqlite3 *db,char *str)
{
char **result;
int nrow,ncolumn,i,j;
char sql[100]={'\0'};
sprintf(sql,"select money from user where id = '%s'",str);
sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,NULL);
if(nrow<=0)
return -1;
return atoi(result[nrow]);
}
存款:
int save(sqlite3 *db,char *str,int money)
{
char **result;
int nrow,ncolumn,i,j;
char sql[100]={'\0'};
sprintf(sql,"select money from user where id = '%s'",str);
sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,NULL);
if(nrow<=0)return -1;
int new_money = atoi(result[nrow]) + money;
sprintf(sql,"update user set money = '%d' where id = '%s'",new_money,str);
if(sqlite3_exec(db,sql,NULL,NULL,NULL))
{
return -1;
}
return new_money;
}
取款:
int take(sqlite3 *db,char *str,int money)
{
char **result;
int nrow,ncolumn,i,j;
char sql[100]={'\0'};
sprintf(sql,"select money from user where id = '%s'",str);
sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,NULL);
if(nrow<=0)return -1;
int new_money = atoi(result[nrow]) - money;
if(new_money<0)return -2;
sprintf(sql,"update user set money = '%d' where id = '%s'",new_money,str);
if(sqlite3_exec(db,sql,NULL,NULL,NULL))
{
return -1;
}
return new_money;
}
销户:
int delete1(sqlite3 *db,char *str)
{
char **result;
int nrow,ncolumn,i,j;
char sql[100]={'\0'};
sprintf(sql,"delete from user where id = '%s'",str);
if(sqlite3_exec(db,sql,NULL,NULL,NULL))
{
return -1;
}
return 0;
}
输出结果:
注册:
登录:
存款:
取款:
销户: