網絡版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