版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_15345177/article/details/87921016
网络版ATM
设计结构体
#ifndef STRUCT_H
#define STRUCT_H
//账号结构体
typedef struct User
{
//账号
int id;
//密码
char password[7];
//身份证号
char ID[19];
//金额
double money;
//锁定标志位
int state;
//在线标志位
int is_online;
}User;
//消息结构体
typedef struct Msg
{
//消息类型
long msg_type;
//错误信息类型
int error_type;
//操作对象
int object_id;
//帐号结构体
User user;
}Msg;
//ip地址操作对象结构体
typedef struct Fd_ip
{
//fd标识符
int fd;
//fd所对应的ip地址
char ip[20];
}Fd_ip;
#endif
客户端
1、进入时的功能开户、销户、登录、解锁
开户:输入姓名、身份证号、设置密码,如果开户成功,则服务器上保存一个账号信号(一个账号存一个文件,文件名建议是账号)。
销户:输入帐号、密码,服务器询问是否确认销户,如果确认则服务器删除帐号文件,并记录帐号。
登录:输入账号、密码,三次错误账号锁定。
解锁:输入账号、身份证号解锁。
2、登录成功:存钱、取钱、转账、查询、修改密码
存钱:输入存钱金额
取钱:输入取钱金额
转账:目标帐号和要转的金额
查询:不需要输入数据
修改密码:输入新密码
客户端主函数
#include"tool.h"
void sigint(int signum)
{
user_exit();
puts("客户端已关闭!");
kill(getpid(),9);
}
//客户端主界面
int main()
{
signal(SIGINT,sigint);
signal(SIGQUIT,sigint);
//进度条
loading();
//创建通信连接
if(-1 == c_s_socket())
{
puts("服务器繁忙,请稍后重试...");
return -1;
}
//客户端主界面
c_main();
}
功能函数(大部分函数都在其中)
头文件
#ifndef TOOL_H
#define TOOL_H
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <getch.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <semaphore.h>
#include <pthread.h>
#include <signal.h>
#include "struct.h"
#define HTONS 1990
#define ADDR "192.168.1.13"
#define SIZE 10
//操作类型
#define CREATE 100
#define LOGIN 200
#define DELETE 300
#define UNLOCK 400
#define STORE 500
#define TAKE 600
#define TRANSFER 700
#define SEARCH 800
#define CHANGE 900
#define USER_EXIT 1000
//错误类型
#define CONNECT_FAILD -1
#define NO_ERROR 0
#define ERROR_id 1
#define ERROR_PASSWORD 2
#define IS_ONLINE 3
#define id_LOCKED 4
#define id_UNLOCKED 5
#define ERROR_ID 6
#define TOO_MORE 7
#define NEW_EQULE_OLD 8
//loading
#define RED "\033[31m"
#define GREEN "\033[32m"
#define YELLOW "\033[33m"
#define BLUE "\033[34m"
#define PORPLE "\033[35m"
#define DGREEN "\033[36m"
Msg c_msg;
int ask;
int answer;
int sockfd;
Fd_ip fd_ip[SIZE];
pid_t pids[9];
//********************************* 公共函数 ********************************
//进度条
void loading(void);
//清理缓冲区
void clear_stdin(void);
//任意键返回
void anykey_continue(void);
//提示信息
void show_msg(char* msg,int sec,int color);
//输入函数
char* get_str(char* str,size_t size);
//密码输入
void password_input(char* str);
//密码规则
int password_rule(char *str);
//打开消息队列
void create_msglist(void);
//********************************* 客户端函数 C ********************************
//客户端主界面
int c_main(void);
//登录成功 用户操作界面
int client_user(void);
//创建c to s通信连接
int c_s_socket(void);
//错误类型判断显示
int error_confirm(int error);
//注册函数
int client_create(void);
//登录
int client_login(void);
//销户
int client_delete(void);
//解锁
int client_unlock(void);
//存钱
int user_store(void);
//取钱
int user_take(void);
//转账
int user_transfer(void);
//查询
int user_search(void);
//修改密码
int user_change(void);
//用户退出
int user_exit(void);
//********************************* 服务端函数 S ********************************
//创建s to c通信连接
int s_c_socket(void);
//开启各项服务
void open_serves(void);
//用户子线程
void* start(void* p);
//客户端断开连接操作
int serve_exit(int fd);
#endif
功能函数内容
#include "tool.h"
//***************************************** 公用函数 *******************************************
//进度条
void loading(void)
{
char buf[101] = {};
int i =0;
char *ptr = "|/-\\";
for(i = 0; i<101; i++)
{
if(i<20) printf(RED);
else if(i<40) printf(YELLOW);
else if(i<60) printf(GREEN);
else if(i<80) printf(DGREEN);
else if(i<90) printf(BLUE);
else printf(PORPLE);
buf[i] = '=';
printf("[%-100s][%%%d][%c]",buf,i,ptr[i%4]);
fflush(stdout);
usleep(100000);
printf("\n");
system("clear");
}
printf("\033[0m");
}
//清理缓冲区
void clear_stdin(void)
{
stdin->_IO_read_ptr=stdin->_IO_read_end;
}
//任意键返回
void anykey_continue(void)
{
clear_stdin();
show_msg("按任意键继续......",1,2);
getch();
}
//提示信息
void show_msg(char* msg,int sec,int color)
{
//红
if(0==color)
printf("\n\033[01;31m%s\n\033[00m\n",msg);
//绿
if(1==color)
printf("\n\033[01;32m%s\n\033[00m\n",msg);
//黄
if(2==color)
printf("\n\033[01;33m%s\n\033[00m\n",msg);
sleep(sec);
}
//输入函数
char* get_str(char* str,size_t size)
{
if(NULL == str) return str;
clear_stdin();
fgets(str,size,stdin);
if(size-1 == strlen(str))
{
if('\n'==str[size-2])
str[size-2]= '\0';
else
clear_stdin();
}
else
str[strlen(str)-1]='\0';
}
//密码输入
void password_input(char* str)
{
for(int i=0;i<7;i++)
{
str[i]=getch();
if(i>0&&127 == str[i])
{
i-=2;
printf("\b \b");
continue;
}
if(127 == str[i])
{
i--;
continue;
}
if('\n'==str[i])
{
str[i]='\0';
break;
}
putchar('*');
}
}
//密码规则
int password_rule(char *str)
{
int len=strlen(str);
if(6!=len)
return -1;
for(int i=0;str[i];i++)
{
if(str[i]<'0' || str[i]>'9')
return -1;
}
return 1;
}
//打开消息队列
void create_msglist(void)
{
key_t c_key = ftok(".",1);
key_t s_key = ftok(".",2);
ask = msgget(c_key,IPC_CREAT|00644);
answer = msgget(s_key,IPC_CREAT|00644);
}
//***************************************** 客户端函数 C ****************************************
//客户端主界面
int c_main(void)
{
while(1)
{
clear_stdin();
system("clear");
puts("-----客户端主界面-----");
puts("1.登录");
puts("2.注册");
puts("3.销户");
puts("4.解锁");
puts("0.退出");
clear_stdin();
switch(getch())
{
case 49:if(1==client_login())client_user();break;
case 50:client_create();break;
case 51:client_delete();break;
case 52:client_unlock();break;
case 48:puts("客户端已关闭!");return 0;
}
}
}
//登录成功 用户操作界面
int client_user(void)
{
while(1)
{
clear_stdin();
system("clear");
puts("-----用户界面-----");
printf("账户ID:%d\n",c_msg.user.id);
puts("-----------------");
puts("1.存入现金");
puts("2.取出现金");
puts("3.转账操作");
puts("4.查询信息");
puts("5.修改密码");
puts("0.退出登录");
/*测试用信息
printf("*msg type:%ld\n",c_msg.msg_type);
printf("*error type:%d\n",c_msg.error_type);
printf("*object_id;:%d\n",c_msg.object_id);
printf("*账户ID:%d\n",c_msg.user.id);
printf("*账户密码:%s\n",c_msg.user.password);
printf("*身份证号码:%s\n",c_msg.user.ID);
printf("*存款:%.2lf\n",c_msg.user.money);
printf("*状态:%d\n",c_msg.user.state);
printf("*在线:%d\n",c_msg.user.is_online);
*/
clear_stdin();
switch(getch())
{
case 49:user_store();break;
case 50:user_take();break;
case 51:user_transfer();break;
case 52:user_search();break;
case 53:user_change();break;
case 48:user_exit();return 0;
}
}
}
//创建c to s通信连接
int c_s_socket(void)
{
//创建socket对象
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(0>sockfd)
{
perror("socket");
return -1;
}
//准备通信地址
struct sockaddr_in addr ={};
addr.sin_family = AF_INET;
addr.sin_port = htons(HTONS);
addr.sin_addr.s_addr = inet_addr(ADDR);
//连接
if(0>connect(sockfd,(struct sockaddr*)&addr,sizeof(addr)))
{
perror("connect");
return -1;
}
//接收连接结果
recv(sockfd,&c_msg,sizeof(Msg),0);
if(1 == error_confirm(c_msg.error_type))
{
show_msg("连接成功!",1,1);
return 1;
}
return -1;
}
//错误类型判断显示
int error_confirm(int error)
{
switch(error)
{
case NO_ERROR: return 1;
case CONNECT_FAILD: show_msg("连接失败!",2,0); break;
case ERROR_id: show_msg("账号不存在!",2,0); break;
case ERROR_PASSWORD:show_msg("密码错误!",2,0); break;
case IS_ONLINE: show_msg("账号已在某处登录!若非本人操作请询问工作人员或拨打 110 报警",3,0); break;
case id_LOCKED: show_msg("账号已锁定!",2,0); break;
case id_UNLOCKED: show_msg("账号未被锁定!",2,0); break;
case ERROR_ID: show_msg("身份证号码错误!",2,0); break;
case TOO_MORE: show_msg("无法提供该金额!",2,0); break;
case NEW_EQULE_OLD: show_msg("错误:新密码与旧密码一致!",2,0); break;
}
c_msg.error_type=NO_ERROR;
return -1;
}
//注册函数
int client_create(void)
{
//操作类型
c_msg.msg_type = CREATE;
clear_stdin();
system("clear");
printf("-----用户开户-----\n");
clear_stdin();
printf("请输入身份证号:");
get_str(c_msg.user.ID,18);
printf("请输入6位密码:");
char buf[7]={};
password_input(buf);
if(-1 == password_rule(buf))
{
show_msg("密码格式错误...",1,0);
return -1;
}
//确认新密码
printf("\n请再次输入密码:");
password_input(c_msg.user.password);
//两次输入不一致,退出
if( 0 != strcmp(buf,c_msg.user.password))
{
show_msg("错误:两次输入的密码不一致!",1,0);
anykey_continue();
return -1;
}
//向服务端发送信息
send(sockfd,&c_msg,sizeof(Msg),0);
//从服务端获取数据
recv(sockfd,&c_msg,sizeof(Msg),0);
show_msg("注册成功!",1,1);
printf("您的账号为:=%d\n",c_msg.user.id);
anykey_continue();
}
//登录函数
int client_login(void)
{
//操作类型
c_msg.msg_type = LOGIN;
clear_stdin();
system("clear");
printf("-----用户登录-----\n");
clear_stdin();
printf("请输入账号:");
scanf("%d",&c_msg.user.id);
clear_stdin();
printf("请输入密码:");
password_input(c_msg.user.password);
//向服务端发送信息
send(sockfd,&c_msg,sizeof(Msg),0);
//从服务端获取数据
recv(sockfd,&c_msg,sizeof(Msg),0);
//错误判断//return 1 才能进入用户界面
if(1 == error_confirm(c_msg.error_type))
{
show_msg("登录成功!",1,1);
return 1;
}
return -1;
}
//销号
int client_delete(void)
{
//操作类型
c_msg.msg_type = DELETE;
clear_stdin();
system("clear");
printf("-----账号销号-----\n");
clear_stdin();
printf("请输入要销号的账号:");
scanf("%d",&c_msg.user.id);
clear_stdin();
printf("请输入密码:");
password_input(c_msg.user.password);
//向服务端发送信息
send(sockfd,&c_msg,sizeof(Msg),0);
//从服务端获取数据
recv(sockfd,&c_msg,sizeof(Msg),0);
//错误判断
if(1 == error_confirm(c_msg.error_type))
{
if(0 < c_msg.user.money)
{
show_msg("账户中还有余额,正在退还余额!",2,1);
printf("退还余额 %.2lf 元,请收好您的钞票。\n",c_msg.user.money);
sleep(2);
}
show_msg("销户成功!",2,1);
return 1;
}
return -1;
}
//解锁
int client_unlock(void)
{
//操作类型
c_msg.msg_type = UNLOCK;
clear_stdin();
system("clear");
printf("-----解锁账号-----\n");
clear_stdin();
printf("请输入要解锁的账号:");
scanf("%d",&c_msg.user.id);
clear_stdin();
printf("请输入身份证号:");
get_str(c_msg.user.ID,20);
//向服务端发送信息
send(sockfd,&c_msg,sizeof(Msg),0);
//从服务端获取数据
recv(sockfd,&c_msg,sizeof(Msg),0);
//错误判断
if(1 == error_confirm(c_msg.error_type))
{
show_msg("解锁成功!",1,1);
printf("您的密码为:%s\n",c_msg.user.password);
anykey_continue();
return 1;
}
return -1;
}
//存钱
int user_store(void)
{
//操作类型
c_msg.msg_type = STORE;
clear_stdin();
system("clear");
printf("-----存入现金-----\n");
clear_stdin();
double sum=0;
printf("请输入要存入的金额:");
scanf("%lf",&sum);
if(0 >= sum)
{
show_msg("不能存入零或小于零的金额!",1,0);
return -1;
}
c_msg.user.money = sum;
clear_stdin();
show_msg("请把现金放入存钞口",1,2);
anykey_continue();
//向服务端发送信息
send(sockfd,&c_msg,sizeof(Msg),0);
show_msg("正在存钞请稍后...",1,2);
//从服务端获取数据
recv(sockfd,&c_msg,sizeof(Msg),0);
show_msg("操作已成功!",1,1);
printf("您的余额为:%.2lf\n",c_msg.user.money);
anykey_continue();
}
//取钱
int user_take(void)
{
//操作类型
c_msg.msg_type = TAKE;
clear_stdin();
system("clear");
printf("-----取出现金-----\n");
double sum=0;
clear_stdin();
printf("请输入要取出的金额:");
scanf("%lf",&sum);
if(0 >= sum)
{
show_msg("不能存入零或小于零的金额!",1,0);
return -1;
}
c_msg.user.money = sum;
//向服务端发送信息
send(sockfd,&c_msg,sizeof(Msg),0);
show_msg("正在取出现金请稍后...",1,2);
//从服务端获取数据
recv(sockfd,&c_msg,sizeof(Msg),0);
//错误判断
if(1 == error_confirm(c_msg.error_type))
{
show_msg("操作已成功!",1,1);
printf("您的余额为:%.2lf\n",c_msg.user.money);
show_msg("请取走您的现金!",2,3);
return 1;
}
return -1;
}
//转账
int user_transfer(void)
{
//操作类型
c_msg.msg_type = TRANSFER;
clear_stdin();
system("clear");
printf("-----转账-----\n");
clear_stdin();
printf("请输入要转账的账户账号:");
scanf("%d",&c_msg.object_id);
if(c_msg.object_id == c_msg.user.id)
{
show_msg("不能给自己转账!",1,0);
return -1;
}
double sum=0;
clear_stdin();
printf("请输入要转账的金额:");
scanf("%lf",&sum);
if(0 >= sum)
{
show_msg("不能存入零或小于零的金额!",1,0);
return -1;
}
c_msg.user.money = sum;
//向服务端发送信息
send(sockfd,&c_msg,sizeof(Msg),0);
show_msg("正在转账请稍后...",1,2);
//从服务端获取数据
recv(sockfd,&c_msg,sizeof(Msg),0);
//错误判断
if(1 == error_confirm(c_msg.error_type))
{
show_msg("转账已成功!",1,1);
printf("您的余额为:%.2lf\n",c_msg.user.money);
anykey_continue();
return 1;
}
return -1;
}
//查询
int user_search(void)
{
//操作类型
c_msg.msg_type = SEARCH;
clear_stdin();
system("clear");
printf("-----查询信息-----\n");
//向服务端发送信息
send(sockfd,&c_msg,sizeof(Msg),0);
//从服务端获取数据
recv(sockfd,&c_msg,sizeof(Msg),0);
//错误判断
if(1 == error_confirm(c_msg.error_type))
{
printf("*账户ID:%d\n",c_msg.user.id);
printf("*身份证号码:%s\n",c_msg.user.ID);
printf("*存款:%.2lf\n",c_msg.user.money);
anykey_continue();
return 1;
}
return -1;
}
//修改密码
int user_change(void)
{
//操作类型
c_msg.msg_type = CHANGE;
clear_stdin();
system("clear");
printf("-----修改密码-----\n");
clear_stdin();
//第一次输入新密码
clear_stdin();
printf("请输入新密码:");
char buf[7]={};
password_input(buf);
//判断密码是否为6位数
if(-1 == password_rule(buf))
{
show_msg("密码格式错误...",1,0);
return -1;
}
//确认新密码
printf("\n请再次输入新密码:");
password_input(c_msg.user.password);
//两次输入不一致,退出
if( 0 != strcmp(buf,c_msg.user.password))
{
show_msg("两次输入的密码不一致!",1,0);
anykey_continue();
return -1;
}
//向服务端发送信息
send(sockfd,&c_msg,sizeof(Msg),0);
show_msg("修改密码中请稍后...",1,2);
//从服务端获取数据
recv(sockfd,&c_msg,sizeof(Msg),0);
//错误判断
if(1 == error_confirm(c_msg.error_type))
{
show_msg("修改成功!",1,1);
printf("您的新密码为:%s\n",c_msg.user.password);
anykey_continue();
return 1;
}
return -1;
}
//用户退出
int user_exit(void)
{
//操作类型
c_msg.msg_type = USER_EXIT;
//向服务端发送信息
send(sockfd,&c_msg,sizeof(Msg),0);
//从服务端获取数据
recv(sockfd,&c_msg,sizeof(Msg),0);
show_msg("成功退出!",1,1);
}
//***************************************** 服务端函数 S ****************************************
//创建s to c通信连接
int s_c_socket(void)
{
Msg s_msg={};
// 创建socket对象
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(0 > sockfd)
{
perror("socket");
return -1;
}
// 准备通信地址
struct sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_port = htons(HTONS);
addr.sin_addr.s_addr = inet_addr(ADDR);
// 绑定socket对象与通信地址
socklen_t len = sizeof(addr);
if(0 > bind(sockfd,(struct sockaddr*)&addr,len))
{
perror("bind");
return -1;
}
// 设置监听socket对象
listen(sockfd,SIZE);
// 等待连接
while(1)
{
struct sockaddr_in from_addr;
int user_fd = accept(sockfd,(struct sockaddr*)&from_addr,&len);
if(0 > user_fd)
{
printf("客户端连接出错...\n");
continue;
}
int i;
for (i=0;i<SIZE;i++)
{
if (fd_ip[i].fd == 0)
{
//记录客户端的fd和ip
fd_ip[i].fd = user_fd;
strcpy(fd_ip[i].ip,inet_ntoa(from_addr.sin_addr));
//线程id
pthread_t pid;
//线程属性
pthread_attr_t attr;
//初始化线程属性
pthread_attr_init(&attr);
//设置线程属性
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
//创建子线程
pthread_create(&pid,&attr,start,&user_fd);
//提示连接成功
s_msg.error_type = NO_ERROR;
send(user_fd,&s_msg,sizeof(Msg),0);
printf("客户端:%s连接成功!\n",fd_ip[i].ip);
break;
}
}
if (SIZE == i)
{
//服务器满了,关闭fd
s_msg.error_type = CONNECT_FAILD;
send(user_fd,&s_msg,sizeof(Msg),0);
puts("服务器已满");
close(user_fd);
}
}
}
//用户子线程
void* start(void* p)
{
int fd =*(int*)p;
Msg s_msg={};
// 收发数据
while(1)
{
//接受信息
if(0 >= recv(fd,&s_msg,sizeof(Msg),0))
{
//服务器退出关闭fd
serve_exit(fd);
//结束线程
pthread_exit(0);
}
//向服务端发送信息
msgsnd(ask,&s_msg,sizeof(Msg)-4,0);
//从服务端接受信息
msgrcv(answer,&s_msg,sizeof(Msg)-4,s_msg.msg_type,0);
send(fd,&s_msg,sizeof(Msg),0);
}
}
//开启各项服务
void open_serves(void)
{
//登录
pid_t pid0=vfork();
if(0 == pid0)
execl("./login","login",NULL);
else
{
perror("vfork login");
pids[0]=pid0;
}
//开户
pid_t pid1=vfork();
if(0 == pid1)
execl("./create","create",NULL);
else
{
perror("vfork create");
pids[1]=pid1;
}
//销户
pid_t pid2=vfork();
if(0 == pid2)
execl("./delete","delete",NULL);
else
{
perror("vfork delete");
pids[2]=pid2;
}
//解锁
pid_t pid3=vfork();
if(0 == pid3)
execl("./unlock","unlock",NULL);
else
{
perror("vfork unlock");
pids[3]=pid3;
}
//存钱
pid_t pid4=vfork();
if(0 == pid4)
execl("./store","store",NULL);
else
{
perror("vfork store");
pids[4]=pid4;
}
//取钱
pid_t pid5=vfork();
if(0 == pid5)
execl("./take","take",NULL);
else
{
perror("vfork take");
pids[5]=pid5;
}
//转账
pid_t pid6=vfork();
if(0 == pid6)
execl("./transfer","transfer",NULL);
else
{
perror("vfork transfer");
pids[6]=pid6;
}
//查询
pid_t pid7=vfork();
if(0 == pid7)
execl("./search","search",NULL);
else
{
perror("vfork search");
pids[7]=pid7;
}
//修改密码
pid_t pid8=vfork();
if(0 == pid8)
execl("./change","change",NULL);
else
{
perror("vfork change");
pids[8]=pid8;
}
//退出登录
pid_t pid9=vfork();
if(0 == pid9)
execl("./logout","logout",NULL);
else
{
perror("vfork logout");
pids[9]=pid9;
}
}
//客户端断开连接操作
int serve_exit(int fd)
{
printf("进行退出\t");
//退出后将位置空出来
for (int i=0;i<SIZE;i++)
{
if (fd == fd_ip[i].fd)
{
fd_ip[i].fd = 0;
close(fd);
printf("%s 退出成功\n",fd_ip[i].ip);
break;
}
}
}
服务端
1、根据消息的类型识别客户端请求的功能。
2、开启服务各项功能的子进程
3、各进程按照消息类型接收消息
服务端主函数
#include"tool.h"
void sigint()
{
printf("\n服务端所有进程已经关闭\n");
msgctl(ask,IPC_RMID,NULL);
msgctl(answer,IPC_RMID,NULL);
for(int i=0;i<9;i++)
{
kill(pids[i],9);
}
close(sockfd);
exit(0);
}
int main()
{
puts("服务器已开启");
signal(SIGINT,sigint);
signal(SIGQUIT,sigint);
//开启各项服务
open_serves();
//创建消息队列
create_msglist();
//创建连接
s_c_socket();
//关闭进程
sigint();
}
功能进程函数
注册
#include"tool.h"
//服务端注册操作
int main()
{
Msg s_msg={CREATE};
//打开消息队列
create_msglist();
while(1)
{
//接受请求信息
msgrcv(ask,&s_msg,sizeof(Msg)-4,s_msg.msg_type,0);
printf("进行注册\t");
//打开计数文件
int count_fd=open("users/count",O_RDWR|O_CREAT,00644);
if(0 > count_fd)
{
perror("open user_ifo");
continue;
}
int count=0;
//读取数量
read(count_fd,&count,sizeof(int));
//计数+1
count++;
//文件指针调到头
lseek(count_fd,0,SEEK_SET);
//保存数量
write(count_fd,&count,sizeof(int));
close(count_fd);
//给予id
s_msg.user.id=10000+count;
//账户id 转换为字符串
char buf[20]={};
sprintf(buf, "users/%d",s_msg.user.id);
//buf:文件名为账户id
int fd=open(buf,O_RDWR|O_CREAT,00644);
if(0 > fd)
{
perror("open user_ifo");
continue;
}
//保存用户信息
write(fd,&s_msg.user,sizeof(User));
close(fd);
//发送答复信息
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
puts("注册成功");
}
}
登录
#include"tool.h"
//服务端登录操作
int main()
{
//printf("login pid=%d\n",getpid());
Msg s_msg={LOGIN};
Msg true_msg={LOGIN};
//打开消息队列
create_msglist();
while(1)
{
true_msg.error_type = NO_ERROR;
//接受请求信息
msgrcv(ask,&s_msg,sizeof(Msg)-4,s_msg.msg_type,0);
printf("进行登录\t");
//账户id 转换为字符串
char buf[20]={};
sprintf(buf, "users/%d",s_msg.user.id);
//buf:文件名为账户id
int fd=open(buf,O_RDWR,00644);
if(0 > fd)
{
puts("账户不存在!");
s_msg.error_type = ERROR_id;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
continue;
}
//从文件中读取客户信息
read(fd,&true_msg.user,sizeof(User));
if(1 == true_msg.user.is_online)
{
puts("账号已登录!");
//发送错误信息
s_msg.error_type = IS_ONLINE;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
close(fd);
continue;
}
if(2 < true_msg.user.state)
{
puts("账户被锁定!");
//发送错误信息
s_msg.error_type = id_LOCKED;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
close(fd);
continue;
}
if(0 != strcmp(s_msg.user.password,true_msg.user.password))
{
puts("密码错误!");
true_msg.user.state ++;
lseek(fd,0,SEEK_SET);
write(fd,&true_msg.user,sizeof(User));
close(fd);
//发送错误信息
s_msg.error_type = ERROR_PASSWORD;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
continue;
}
//登陆标志设置为 1 上线
true_msg.user.is_online = 1;
lseek(fd,0,SEEK_SET);
write(fd,&true_msg.user,sizeof(User));
close(fd);
//发送答复消息
msgsnd(answer,&true_msg,sizeof(Msg)-4,0);
puts("登陆成功");
}
}
解锁
#include "tool.h"
//服务端解锁操作
int main()
{
//printf("reset pid=%d\n",getpid());
Msg s_msg={UNLOCK};
Msg true_msg={UNLOCK};
//打开消息队列
create_msglist();
while(1)
{
//接受请求信息
msgrcv(ask,&s_msg,sizeof(Msg)-4,s_msg.msg_type,0);
printf("进行解锁\t");
//账户id 转换为字符串
char buf[20]={};
sprintf(buf, "users/%d",s_msg.user.id);
//buf:文件名为账户id
int fd=open(buf,O_RDWR,00644);
if(0 > fd)
{
puts("账户不存在!");
s_msg.error_type = ERROR_id;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
continue;
}
read(fd,&true_msg.user,sizeof(User));
if(3 > true_msg.user.state && 0 == true_msg.user.is_online)
{
puts("账户未被锁定!");
s_msg.error_type = id_UNLOCKED;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
close(fd);
continue;
}
if(0 != strcmp(s_msg.user.ID,true_msg.user.ID))
{
puts("身份证号码错误!");
s_msg.error_type = ERROR_ID;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
close(fd);
continue;
}
if(1 == true_msg.user.is_online)
{
puts("账号已在线!");
s_msg.error_type=IS_ONLINE;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
close(fd);
continue;
}
//解锁标志位 置为 0
true_msg.user.state = 0;
true_msg.user.is_online = 0;
lseek(fd,0,SEEK_SET);
write(fd,&true_msg.user,sizeof(User));
close(fd);
//发送答复消息
msgsnd(answer,&true_msg,sizeof(Msg)-4,0);
puts("解锁成功");
}
}
销号
#include "tool.h"
//服务端销号操作
int main()
{
//printf("delete pid=%d\n",getpid());
Msg s_msg={DELETE};
Msg true_msg={DELETE};
//打开消息队列
create_msglist();
while(1)
{
//接受请求信息
msgrcv(ask,&s_msg,sizeof(Msg)-4,s_msg.msg_type,0);
printf("进行销号\t");
//账户id 转换为字符串
char buf[20]={};
sprintf(buf, "users/%d",s_msg.user.id);
//buf:文件名为账户id
int fd=open(buf,O_RDWR,00644);
if(0 > fd)
{
puts("账户不存在!");
s_msg.error_type=ERROR_id;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
continue;
}
//从文件中读取客户信息
read(fd,&true_msg.user,sizeof(User));
if(0 != strcmp(s_msg.user.password,true_msg.user.password))
{
puts("密码错误!");
s_msg.error_type=ERROR_PASSWORD;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
close(fd);
continue;
}
if(1 == true_msg.user.is_online)
{
puts("账号已在线!");
s_msg.error_type=IS_ONLINE;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
close(fd);
continue;
}
//要删除的账户id 转换为字符串
char delete_buf[20]={};
sprintf(delete_buf, "deleted/%d",s_msg.user.id);
//删除账户保存到另一文件夹
int delete_fd=open(delete_buf,O_RDWR|O_CREAT,00644);
if(0 > delete_fd)
{
perror("delete_fd");
}
write(delete_fd,&true_msg.user,sizeof(User));
close(delete_fd);
//发送答复消息
msgsnd(answer,&true_msg,sizeof(Msg)-4,0);
//用户余额清零
true_msg.user.money = 0;
lseek(fd,0,SEEK_SET);
write(fd,&true_msg.user,sizeof(User));
close(fd);
//删除文件
remove(buf);
puts("销号成功");
}
}
存钱
#include "tool.h"
//服务端存钱操作
int main()
{
//printf("store pid=%d\n",getpid());
Msg s_msg={STORE};
Msg true_msg={STORE};
//打开消息队列
create_msglist();
while(1)
{
true_msg.error_type = NO_ERROR;
//接受请求信息
msgrcv(ask,&s_msg,sizeof(Msg)-4,s_msg.msg_type,0);
printf("进行存钱\t");
//账户id 转换为字符串
char buf[20]={};
sprintf(buf, "users/%d",s_msg.user.id);
//buf:文件名为账户id
int fd=open(buf,O_RDWR,00644);
if(0 > fd)
{
puts("账户不存在!");
s_msg.error_type = ERROR_id;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
continue;
}
read(fd,&true_msg.user,sizeof(User));
true_msg.user.money += s_msg.user.money;
lseek(fd,0,SEEK_SET);
write(fd,&true_msg.user,sizeof(User));
close(fd);
//向客户端发送信息
msgsnd(answer,&true_msg,sizeof(Msg)-4,0);
puts("存钱成功");
}
}
取钱
#include "tool.h"
//服务端取钱操作
int main()
{
//printf("take pid=%d\n",getpid());
Msg s_msg={TAKE};
Msg true_msg={TAKE};
//打开消息队列
create_msglist();
while(1)
{
true_msg.error_type = NO_ERROR;
//接受请求信息
msgrcv(ask,&s_msg,sizeof(Msg)-4,s_msg.msg_type,0);
printf("进行取钱\t");
//账户id 转换为字符串
char buf[20]={};
sprintf(buf, "users/%d",s_msg.user.id);
//buf:文件名为账户id
int fd=open(buf,O_RDWR,00644);
if(0 > fd)
{
puts("账户不存在!");
s_msg.error_type = ERROR_id;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
continue;
}
read(fd,&true_msg.user,sizeof(User));
if(true_msg.user.money < s_msg.user.money)
{
puts("无法提供该金额!");
true_msg.error_type = TOO_MORE;
msgsnd(answer,&true_msg,sizeof(Msg)-4,0);
close(fd);
continue;
}
true_msg.user.money -= s_msg.user.money;
lseek(fd,0,SEEK_SET);
write(fd,&true_msg.user,sizeof(Msg));
close(fd);
//向客户端发送信息
msgsnd(answer,&true_msg,sizeof(Msg)-4,0);
puts("取钱成功");
}
}
转账
#include "tool.h"
//服务端转账操作
int main()
{
//printf("transfer pid=%d\n",getpid());
Msg s_msg={TRANSFER};
Msg truemsg_from={TRANSFER};
Msg truemsg_to={TRANSFER};
//打开消息队列
create_msglist();
while(1)
{
truemsg_from.error_type = NO_ERROR;
truemsg_to.error_type = NO_ERROR;
//接受请求信息
msgrcv(ask,&s_msg,sizeof(Msg)-4,s_msg.msg_type,0);
printf("进行转账\t");
//账户ID 转换为字符串
char buff[20]={};
char buft[20]={};
sprintf(buff, "users/%d",s_msg.user.id);
sprintf(buft, "users/%d",s_msg.object_id);
//buf:文件名为账户id
int fdf=open(buff,O_RDWR,00644);
if(0 > fdf)
{
puts("账户不存在!");
s_msg.error_type = ERROR_id;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
close(fdf);
continue;
}
read(fdf,&truemsg_from.user,sizeof(User));
//printf("truemsg_from.user.money 1 =%lf\n",truemsg_from.user.money);
//buft:转账账户文件
int fdt=open(buft,O_RDWR,00644);
if(0 > fdt)
{
puts("转账账户不存在!");
truemsg_from.error_type = ERROR_id;
msgsnd(answer,&truemsg_from,sizeof(Msg)-4,0);
close(fdt);
continue;
}
read(fdt,&truemsg_to.user,sizeof(User));
//转账金额大于存款
if(truemsg_from.user.money < s_msg.user.money)
{
puts("无法转账该金额!");
truemsg_from.error_type = TOO_MORE;
msgsnd(answer,&truemsg_from,sizeof(Msg)-4,0);
close(fdf);
close(fdt);
continue;
}
//转账账户 + 转账金额
//本人账户 - 转账金额
truemsg_to.user.money += s_msg.user.money;
truemsg_from.user.money -= s_msg.user.money;
//printf("truemsg_from.user.money 2 =%lf\n",truemsg_from.user.money);
//写入两个账户信息
lseek(fdf,0,SEEK_SET);
write(fdf,&truemsg_from.user,sizeof(User));
close(fdf);
lseek(fdt,0,SEEK_SET);
write(fdt,&truemsg_to.user,sizeof(User));
close(fdt);
//向客户端发送信息
msgsnd(answer,&truemsg_from,sizeof(Msg)-4,0);
puts("转账成功");
}
}
查询信息
#include "tool.h"
//服务端查询操作
int main()
{
//printf("search pid=%d\n",getpid());
Msg s_msg = {SEARCH};
//打开消息队列
create_msglist();
while(1)
{
//接受请求信息
msgrcv(ask,&s_msg,sizeof(Msg)-4,s_msg.msg_type,0);
printf("查询信息\t");
//账户id 转换为字符串
char buf[20]={};
sprintf(buf, "users/%d",s_msg.user.id);
//buf:文件名为账户id
int fd=open(buf,O_RDWR,00644);
if(0 > fd)
{
puts("账户不存在!");
s_msg.error_type = ERROR_id;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
continue;
}
//从文件中读取客户信息
read(fd,&s_msg.user,sizeof(User));
close(fd);
//向客户端发送客户信息
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
puts("查询成功");
}
}
修改密码
#include "tool.h"
//服务端存钱操作
int main()
{
//printf("change pid=%d\n",getpid());
Msg s_msg={CHANGE};
Msg true_msg={CHANGE};
//打开消息队列
create_msglist();
while(1)
{
true_msg.error_type = NO_ERROR;
//接受请求信息
msgrcv(ask,&s_msg,sizeof(Msg)-4,s_msg.msg_type,0);
printf("进行存钱\t");
//账户id 转换为字符串
char buf[20]={};
sprintf(buf, "users/%d",s_msg.user.id);
//buf:文件名为账户id
int fd=open(buf,O_RDWR,00644);
if(0 > fd)
{
puts("账户不存在!");
s_msg.error_type = ERROR_id;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
continue;
}
//从文件中读取客户信息
read(fd,&true_msg.user,sizeof(User));
if(0 == strcmp(true_msg.user.password,s_msg.user.password))
{
puts("新旧密码一致!");
true_msg.error_type = NEW_EQULE_OLD;
msgsnd(answer,&true_msg,sizeof(Msg)-4,0);
close(fd);
continue;
}
strcpy(true_msg.user.password,s_msg.user.password);
//新密码写入文件
lseek(fd,0,SEEK_SET);
write(fd,&true_msg.user,sizeof(User));
close(fd);
//向客户端发送客户信息
msgsnd(answer,&true_msg,sizeof(Msg)-4,0);
puts("修改密码成功");
}
}
退出登录
#include "tool.h"
//服务端退出登录操作
int main()
{
//printf("logout pid=%d\n",getpid());
Msg s_msg = {USER_EXIT};
Msg true_msg = {USER_EXIT};
//打开消息队列
create_msglist();
while(1)
{
true_msg.error_type = NO_ERROR;
//接受请求信息
msgrcv(ask,&s_msg,sizeof(Msg)-4,s_msg.msg_type,0);
printf("退出登录\t");
//账户id 转换为字符串
char buf[20]={};
sprintf(buf, "users/%d",s_msg.user.id);
//buf:文件名为账户id
int fd=open(buf,O_RDWR,00644);
if(0 > fd)
{
puts("账户不存在!");
s_msg.error_type = ERROR_id;
msgsnd(answer,&s_msg,sizeof(Msg)-4,0);
continue;
}
//从文件中读取客户信息
read(fd,&true_msg.user,sizeof(User));
true_msg.user.is_online = 0;
//状态写入文件
lseek(fd,0,SEEK_SET);
write(fd,&true_msg.user,sizeof(User));
close(fd);
//向客户端发送客户信息
msgsnd(answer,&true_msg,sizeof(Msg)-4,0);
puts("退出登录成功");
}
}
Makefile
all:
gcc -std=gnu99 -c tool.c
gcc -std=gnu99 -c client.c
gcc -std=gnu99 -c serve.c
gcc -std=gnu99 -c create.c
gcc -std=gnu99 -c login.c
gcc -std=gnu99 -c delete.c
gcc -std=gnu99 -c unlock.c
gcc -std=gnu99 -c store.c
gcc -std=gnu99 -c take.c
gcc -std=gnu99 -c transfer.c
gcc -std=gnu99 -c search.c
gcc -std=gnu99 -c change.c
gcc -std=gnu99 -c logout.c
gcc -std=gnu99 create.c tool.c -o create -lpthread
gcc -std=gnu99 login.c tool.c -o login -lpthread
gcc -std=gnu99 delete.c tool.c -o delete -lpthread
gcc -std=gnu99 unlock.c tool.c -o unlock -lpthread
gcc -std=gnu99 store.c tool.c -o store -lpthread
gcc -std=gnu99 take.c tool.c -o take -lpthread
gcc -std=gnu99 transfer.c tool.c -o transfer -lpthread
gcc -std=gnu99 search.c tool.c -o search -lpthread
gcc -std=gnu99 change.c tool.c -o change -lpthread
gcc -std=gnu99 logout.c tool.c -o logout -lpthread
gcc -std=gnu99 client.c tool.c -o client -lpthread
gcc -std=gnu99 serve.c tool.c -o serve -lpthread