小项目:网络版ATM(C)

网络版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
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BAMS是一个完全开源的政企信息管理系统基础框架。它是轻量级的,简单易学的(学习成本真的很低,没有extjs,没有easyUI,没有繁琐的js UI库。只要java基础扎实,再稍懂一点js即可,真的是为java开发人员量身定制的一套框架啊),框架以Spring Framework为核心、Jsp+Dwr作为模型视图控制器、Hibernate作为数据库操作层。BAMS 2.5 更新日志:2015-07-091、修复了日志无法输出的BUG,增加slf4j lo4j绑定,删除commons-logging,统一通过slf4j使用log4j2、更新 Excel的导入导出功能,使用SpingMVC代替Servlet接收请求,简化代码3、将Word的导出设置为 多例模式,解决线程安全问题。4、新增日常工作已办任务撤销功能,重构日常工作部分代码5、新增util.spring包中可以在ApplicationContext环境外获取bean的工具类.6、重构代码生成部分代码框架定位:BAMS是一个 开源的政企信息管理系统 基础框架。主要定位于“政企信息管理”领域,可用政企信息管理类系统。BAMS是非常强调开发的高效性、健壮性和安全性的。 目前的平台还是主要针对开发人员。 BAMS的业务构建是基于流程引擎Activiti+代码生成器来共同完成流程业务和非流程业务的快速开发。感谢咖啡兔、临远对activiti的深入研究 希望BAMS能够对那些正在或即将开发自己团队的J2EE应用快速开发平台的个人或公司能有所启发! 框架适用环境:操作系统:windows、linux JDK版本:1.6、1.7 tomcat版本:6.x、7.x 数据库:mysql、oracle 浏览器版本:IE7以上系列、chrome系列、火狐

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值