client.h
/**************(头文件)*************/
#include
#include
#include
#include
#include
#include
#include
#include//父子进程
#include
#include
#define DATABASE "user.db"
#define N 521
typedef struct //登陆信息
{
int type;//判断是否为管理员
char name[N];
char passwd[N];
int no;
}USER;
typedef struct //员工信息
{
char name[N];//姓名
char addr[N];//地址
int age;//年龄
int level;//评级
int no;//编号
double salary;//工资
char phone[N];//手机号
int type;//员工级别
}INFO;
typedef struct{ //传输信息结构体
int sign; //操作成功还是失败 0成功 1失败
int type;//判断操作类型
USER user; //员工登陆信息
INFO info;//员工信息结构体
char data[N];//操作成功或者失败的消息
}MSG;
/*********************************
*函数
***********************************/
int land(int sockfd, MSG *msg);
int add(int sockfd, MSG *msg);
int change(int sockfd, MSG *msg);
int find(int sockfd, MSG *msg);
int change1(int sockfd, MSG *msg);
client.c
/**********************************
* Copyright (C), 2017
* FileName: client.c
* Description: 1.创建tcp客户端
* 2.连接服务端
* 3.等待用户等级认证
* 4.发送增、删、改、查请求
* Version: 1.3
* Function:
* History:
***********************************/
#include"client.h"
int main(int argc, const char *argv[])
{
int sockfd;
int k;
struct sockaddr_in serveraddr;
int n; //用户选项
MSG msg;
//输入检测
if(argc != 3)
{
printf("Usag:%s serverip port\n",argv[0]);
return -1;
}
//创建套接字
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("fail to socket.\n");
return -1;
}
//填充sockaddr_in结构体
bzero(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//连接
if(connect(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)) < 0)
{
perror("fail to connect");
return -1;
}
//查询系统使用
while(1)
{
printf("**********************************\n");
printf("* 1 land 2 exit *\n");
printf("**********************************\n");
printf("Please choose:");
scanf("%d",&n);
getchar();
switch(n){
case 1:
k = land(sockfd,&msg);
if(k == 0)
{
goto next1;
}
if(k == 1)
{
goto next2;
}
printf("msg.data = %s\n",msg.data);
break;
case 2:
close(sockfd);
exit(0);
break;
default:
printf("Invalid data cmd.\n");
}
}
next1:
while(1)
{
printf("*************welcome super!***************\n");
printf("* 1 add 2 change passwd 3 find 4delete 5 change info 6 exit *\n");
printf("*******************************************\n");
printf("Please choose:");
scanf("%d",&n);
getchar();
(msg.user).type = 0;
switch(n){
case 1:
add(sockfd,&msg);
break;
case 2:
change(sockfd,&msg);
break;
case 3:
find(sockfd,&msg);
break;
case 4:
delete(sockfd,&msg);
break;
case 5:
change1(sockfd,&msg);
break;
case 6:
close(sockfd);
exit(0);
break;
default:
printf("Invalid data cmd.\n");
}
}
next2:
while(1)
{
printf("***************** welcome staff*******************\n");
printf("* 1 change passwd 2 find 3 chenge info 4 exit *\n");
printf("********************************************\n");
printf("Please choose:");
scanf("%d",&n);
getchar();
switch(n){
case 1:
change(sockfd,&msg);
break;
case 2:
find(sockfd,&msg);
break;
case 3:
change1(sockfd,&msg);
break;
case 4:
close(sockfd);
exit(0);
break;
default:
printf("Invalid data cmd.\n");
}
}
return 0;
}
/*********************************
*用户登陆函数
***********************************/
int land(int sockfd, MSG *msg)
{
//登陆选项1
msg->type = 1;
printf("Please input name:\n");
scanf("%s",msg->user.name);
printf("Please input passwd:\n");
scanf("%s",msg->user.passwd);
//发送账号密码
if(send(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to send.\n");
return -1;
}
//接收用户等级
if(recv(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to recv.\n");
return -1;
}
//本次操作如果失败直接返回
if(msg->sign == 0)
{
printf("--------failed!------------\n");
return -1;
}
//如果是超级用户返回0 否则返回1
if(msg->user.type == 0)
return 0;
if(msg->user.type == 1)
return 1;
return 0;
}
/*********************************
*增加用户函数
***********************************/
int add(int sockfd, MSG *msg)
{
//确定操作类型
msg->type=2;
printf("please input usertype (super 0 or staff 1)> ");
scanf("%d",&(msg->user).type);
printf("please input username > ");
scanf("%s",(msg->user).name);
strcpy((msg->info).name,(msg->user).name);
printf("please input userpasswd > ");
scanf("%s",(msg->user).passwd);
printf("please input infoaddr > ");
scanf("%s",(msg->info).addr);
printf("please input infoage > ");
scanf("%d",&((msg->info).age));
printf("please input infolevel > ");
scanf("%d",&((msg->info).level));
printf("please input infono > ");
scanf("%d",&((msg->info).no));
printf("please input infosalary > ");
scanf("%lf",&(msg->info).salary);
printf("please input infophone > ");
scanf("%s",(msg->info).phone);
printf("please input infotype >");
scanf("%d",&((msg->info).type));
if(send(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to send.\n");
return -1;
}
//接收成功与否
if(recv(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to recv.\n");
return -1;
}
//本次操作如果失败直接返回
if(msg->sign == 0)
{
printf("--------failed!------------\n");
return -1;
}
//操作成功打印成功信息
printf("add success!\n");
return 0;
}
/*********************************
*修改密码函数
***********************************/
int change(int sockfd, MSG *msg)
{
//确定操作类型
msg->type=3;
//看是否有选择名字权限
if((msg->user).type == 0)
{
printf("please input username who you want to change> ");
scanf("%s",(msg->user).name);
}
//修改的密码
printf("please input userpasswd who you want to change>");
scanf("%s",(msg->user).passwd);
if(send(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to send.\n");
return -1;
}
//接收成功与否
if(recv(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to recv.\n");
return -1;
}
//本次操作如果失败直接返回
if(msg->sign == 0)
{
printf("--------failed!------------\n");
return -1;
}
//操作成功打印成功信息
printf("change success!\n");
return 0;
}
/*********************************
*查找信息函数
***********************************/
int find(int sockfd, MSG *msg)
{
//确定操作类型
msg->type=4;
//看是否有选择名字权限
if((msg->user).type == 0)
{
printf("please input username who you want to find> ");
scanf("%s",(msg->user).name);
}
if(send(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to send.\n");
return -1;
}
//接收成功与否
if(recv(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to recv.\n");
return -1;
}
//本次操作如果失败直接返回
if(msg->sign == 0)
{
printf("--------failed!------------\n");
return -1;
}
//操作成功打印成功信息
printf("%s\n",msg->data);
return 0;
}
/*********************************
*删除用户函数
***********************************/
int delete(int sockfd, MSG *msg)
{
//确定操作类型
msg->type=5;
printf("please input username who you want to delete> ");
scanf("%s",(msg->user).name);
if(send(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to send.\n");
return -1;
}
//接收成功与否
if(recv(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to recv.\n");
return -1;
}
//本次操作如果失败直接返回
if(msg->sign == 0)
{
printf("--------failed!------------\n");
return -1;
}
//操作成功打印成功信息
printf("%s\n",msg->data);
return 0;
}
/*********************************
*改变信息函数
***********************************/
int change1(int sockfd, MSG *msg)
{
//确定操作类型
msg->type=6;
//看是否有选择名字权限以及修改工资的权限
if((msg->user).type == 0)
{
printf("please input username who you want to change> ");
scanf("%s",(msg->user).name);
printf("please input salary what you want to change>");
scanf("%lf",&(msg->info).salary);
}
//修改的地址
printf("please input addr what you want to change>");
scanf("%s",(msg->info).addr);
if(send(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to send.\n");
return -1;
}
//接收成功与否
if(recv(sockfd,msg,sizeof(MSG),0) < 0)
{
printf("fail to recv.\n");
return -1;
}
//本次操作如果失败直接返回
if(msg->sign == 0)
{
printf("--------failed!------------\n");
return -1;
}
//操作成功打印成功信息
printf("change1 success!\n");
return 0;
}
server.h
/**************(头文件)*************/
#include
#include
#include
#include
#include
#include
#include
#include//父子进程
#include
#include
#define DATABASE "user.db"
#define N 521
typedef struct //登陆信息
{
int type;//判断是否为管理员
char name[N];
char passwd[N];
int no;
}USER;
typedef struct //员工信息
{
char name[N];//姓名
char addr[N];//地址
int age;//年龄
int level;//评级
int no;//编号
double salary;//工资
char phone[N];//手机号
int type;//员工级别
}INFO;
typedef struct{ //传输信息结构体
int sign; //操作成功还是失败 0成功 1失败
int type;//判断操作类型
USER user; //员工登陆信息
INFO info;//员工信息结构体
char data[N];//操作成功或者失败的消息
}MSG;
/**************(函数)*************/
//注册第一个超级用户
int register_super(sqlite3 *db);
//处理函数
int do_client(int acceptfd,sqlite3 *db);
//登陆函数
int land(int acceptfd, MSG *msg,sqlite3 *db);
//增加函数
int add(int acceptfd, MSG *msg,sqlite3 *db);
//修改密码函数
int change(int acceptfd, MSG *msg,sqlite3 *db);
//查找函数
int find(int acceptfd, MSG *msg,sqlite3 *db);
//删除函数
int delete(int acceptfd, MSG *msg,sqlite3 *db);
//修改信息函数
int change1(int acceptfd, MSG *msg,sqlite3 *db);
//互斥检测
int mutex_front(MSG *msg,sqlite3 *db);
//解锁
int mutex_after(MSG *msg,sqlite3 *db);
server.c
/**********************************
* Copyright (C), 2017
* FileName: sever.c
* Description: 1.数据库初始化检测
* 2.创建tcp服务端
* 3.服务器等待连接
* 4.接收用户增、删、改、查请求
* Version: 1.3
* Function:
* History:
***********************************/
#include"sever.h"
int main(int argc, const char *argv[])
{
sqlite3 * db; //数据库
char *errmsg; //数据库错误信息
int sockfd; //服务端套接字
int acceptfd; //接收到的套接字
struct sockaddr_in serveraddr;
MSG msg;
USER user;
pid_t pid;
//输入检测
if(argc != 3)
{
printf("Usag:%s serverip port\n",argv[0]);
return -1;
}
//打开数据库
if(sqlite3_open(DATABASE,&db) != SQLITE_OK)
{
printf("%s\n",sqlite3_errmsg(db));
return -1;
}
//创建密码表
sqlite3_exec(db,"create table book1 (type Integer, name text primary key,passwd text, no Integer);",NULL,NULL,&errmsg);
//创建信息表
sqlite3_exec(db,"create table book2 (name text primary key, addr char, age char, level char, no char,salary float, phone char,type char);",NULL,NULL,&errmsg);
//注册超级用户
register_super(db);
//创建套接字
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("fail to socket.\n");
return -1;
}
//优化允许绑定地址快速重用
int b_reuse = 1;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
//填充sockaddr_in结构体
bzero(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//绑定
if(bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)) < 0)
{
perror("fail to bind");
return -1;
}
//监听
if(listen(sockfd,5) < 0)
{
printf("fail to listen\n");
return -1;
}
//处理僵尸进程
signal(SIGCHLD,SIG_IGN);
//并发服务器
while(1)
{
//接收客户端请求
if((acceptfd = accept(sockfd,NULL,NULL)) < 0)
{
perror("fail to accept");
return -1;
}
//创建子进程
if((pid = fork()) < 0)
{
perror("fail to fork");
return -1;
}
else if(pid == 0)//子进程执行操作
{
close(sockfd);
do_client(acceptfd,db);
}
else //父进程等待接收客户端请求
{
close(acceptfd);
}
}
return 0;
}
//注册第一个超级用户
int register_super(sqlite3 *db)
{
char * errmsg;
char sql[128];
//创建超级用户华清123
sprintf(sql,"insert into book1 values(0,'huaqing','123',0);");
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
printf("huaqing name alread exist!\n");
}
else
{
printf("huaqing name make sucess!\n");
}
return 0;
}
/**********************************
*处理客户端的所有请求
***********************************/
int do_client(int acceptfd,sqlite3 *db)
{
MSG msg;
while(recv(acceptfd , &msg, sizeof(msg),0) > 0)
{
switch(msg.type)
{
case 1: //登陆
land(acceptfd,&msg,db);
break;
case 2://增加用户
add(acceptfd,&msg,db);
break;
case 3://修改用户密码
change(acceptfd,&msg,db);
break;
case 4://查找用户
find(acceptfd,&msg,db);
break;
case 5://删除用户
delete(acceptfd,&msg,db);
case 6://修改用户信息
change1(acceptfd,&msg,db);
break;
default:
printf("Invalid data msg.\n");
}
}
printf("client exit.\n");
close(acceptfd);
exit(0);
return 0;
}
/**********************************
*登陆函数
***********************************/
int land(int acceptfd, MSG *msg,sqlite3 *db)
{
int nrow;
int ncloumn;
char sql[128];
char *errmsg;
char **resultp;
char chaoji[] = "0" ;//用来判断用户类型
//匹配用户信息是否与密码表中相同
sprintf(sql,"select * from book1 where name = '%s' and passwd = '%s';"
,msg->user.name,msg->user.passwd);
if(sqlite3_get_table(db, sql, &resultp, &nrow, &ncloumn, &errmsg) != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
//密码表中存在改用户
if(nrow == 1)
{
strcpy(msg->data,"denglu OK");
msg->sign = 1; //代表操作成功
//判断是管理员还是普通用户
if(strcmp(chaoji,resultp[ncloumn]) == 0) //管理员
{
msg->user.type = 0;
}
else //普通用户
{
msg->user.type = 1;
}
}
//密码表中不存在改用户
if(nrow == 0)
{
strcpy(msg->data,"usr/passwd wrong");
msg->sign = 0; //代表操作失败
}
//返回用户等级信息
if(send(acceptfd,msg,sizeof(MSG),0) < 0)
{
perror("fail to send");
}
return 0;
}
/**********************************
*添加用户函数
***********************************/
int add(int acceptfd, MSG *msg,sqlite3 *db)
{
char * errmsg;
char sql[521];
int k;
//添加用户登陆信息
sprintf(sql,"insert into book1 values('%d','%s','%s',0);"
,msg->user.type,msg->user.name,msg->user.passwd);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
strcpy(msg->data,"usr name alread exist");
}
else
{
k = 1;//添加登陆信息成功
strcpy(msg->data,"user OK");
}
//添加用户详细信息
sprintf(sql,"insert into book2 values('%s','%s','%d','%d','%d','%f','%s','%d');"
,msg->info.name,msg->info.addr,msg->info.age,msg->info.level,msg->info.no,msg->info.salary,msg->info.phone,msg->info.type);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
strcpy(msg->data,"usr name alread exist");
}
else
{
k = k+1;//添加用户详细信息成功
strcpy(msg->data,"info OK");
}
if(k==2)//两者都成功
{
msg->sign = 1; //成功标志
strcpy(msg->data,"add OK!");//成功术语
}
else
{
msg->sign = 0;//失败标志
strcpy(msg->data,"add faild!");//失败术语
}
//将是否成功的消息返回去
if(send(acceptfd,msg,sizeof(MSG),0) < 0)
{
perror("fail to send");
}
return 0;
}
/**********************************
*改变密码的函数
***********************************/
int change(int acceptfd, MSG *msg,sqlite3 *db)
{
char * errmsg;
char sql[521];
int k;
char **resultp;
int nrow;
int ncloumn;
//互斥检测
if(mutex_front(msg,db) == -1)//如果有锁,直接返回
{
msg->sign = 0;
if(send(acceptfd,msg,sizeof(MSG),0) < 0)
{
perror("fail to send");
}
return 0;
}
//更新密码
sprintf(sql,"update book1 set passwd = %s where name = '%s' ",
msg->user.passwd,msg->user.name);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
printf("change failed!\n");
strcpy(msg->data,"change faild!");
msg->sign = 0; //失败标志
}
else
{
strcpy(msg->data,"change success!");
msg->sign = 1; //成功标志
}
//用于互斥检测
//printf("wait input a num......\n");
//int a;
//scanf("%d",&a);
//将是否成功的消息返回去
if(send(acceptfd,msg,sizeof(MSG),0) < 0)
{
perror("fail to send");
}
//互斥解锁
mutex_after(msg,db);
return 0;
}
/**********************************
*查询信息函数
***********************************/
int find(int acceptfd, MSG *msg,sqlite3 *db)
{
char sql[128] = {};
char *errmsg;
char **resultp;
int nrow;
int ncloum;
int i,j;
int index = 0;
sprintf(sql,"select *from book2 where name = '%s' ",msg->user.name);
if(sqlite3_get_table(db,sql,&resultp,&nrow,&ncloum,&errmsg) != SQLITE_OK)
{
printf("%s\n",errmsg);
msg->sign = 0; //失败标志
}
else
{
msg->sign = 1; //成功标志
}
strcpy(msg->data,":");
index = ncloum;
for(j = 0; j < ncloum; j++)
{
strcat(msg->data,resultp[index++]);
strcat(msg->data," - ");
}
//将是否成功的消息返回去
if(send(acceptfd,msg,sizeof(MSG),0) < 0)
{
perror("fail to send");
}
return 0;
}
int delete(int acceptfd, MSG *msg,sqlite3 *db)
{
int k = 0;
int nrow;
int ncloumn;
char * errmsg;
char sql[521];
char **resultp;
//互斥检测
if(mutex_front(msg,db) == -1)//如果有锁,直接返回
{
msg->sign = 0;
if(send(acceptfd,msg,sizeof(MSG),0) < 0)
{
perror("fail to send");
}
return 0;
}
//删除用户对应的密码表
sprintf(sql,"delete from book1 where name = '%s' ",msg->user.name);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
printf("change failed!\n");
strcpy(msg->data,"change faild!");
k = 1;
}
else
{
strcpy(msg->data,"delete success!");
msg->sign = 1; //成功标志
}
//删除用户对应的信息表
sprintf(sql,"delete from book2 where name = '%s' ",msg->user.name);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
printf("delete failed!\n");
strcpy(msg->data,"delete faild!");
k = 1;
}
else
{
strcpy(msg->data,"delete success!");
msg->sign = 1; //成功标志
}
if(k == 1)
msg->sign = 0; //失败标志
//将是否成功的消息返回去
if(send(acceptfd,msg,sizeof(MSG),0) < 0)
{
perror("fail to send");
}
//互斥解锁
mutex_after(msg,db);
return 0;
}
/**********************************
*修改信息函数
***********************************/
int change1(int acceptfd, MSG *msg,sqlite3 *db)
{
char * errmsg;
char sql[521];
int k;
char **resultp;
int nrow;
int ncloumn;
//互斥检测
if(mutex_front(msg,db) == -1)//如果有锁,直接返回
{
msg->sign = 0;
if(send(acceptfd,msg,sizeof(MSG),0) < 0)
{
perror("fail to send");
}
return 0;
}
//如果是超级用户就执行改工资操作
if((msg->user).type == 0)
{
sprintf(sql,"update book2 set salary = %lf where name = '%s' ",msg->info.salary,msg->user.name);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
printf("change1 failed!\n");
strcpy(msg->data,"change faild!");
msg->sign = 0; //失败标志
}
else
{
strcpy(msg->data,"change success!");
msg->sign = 1; //成功标志
}
}
//普通用户和超级用户都可以改以下信息
sprintf(sql,"update book2 set addr = '%s' where name = '%s' ",msg->info.addr,msg->user.name);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
printf("change2 failed!\n");
strcpy(msg->data,"change faild!");
msg->sign = 0; //失败标志
}
else
{
strcpy(msg->data,"change success!");
msg->sign = 1; //成功标志
}
//将是否成功的消息返回去
if(send(acceptfd,msg,sizeof(MSG),0) < 0)
{
perror("fail to send");
}
//互斥解锁
mutex_after(msg,db);
return 0;
}
/**********************************
*互斥检测
***********************************/
int mutex_front(MSG *msg,sqlite3 *db)
{
char * errmsg;
char sql[521];
char **resultp;
int nrow;
int ncloumn;
//互斥检测开始
sprintf(sql,"select * from book1 where name = '%s' and no = 1;",msg->user.name);
sqlite3_get_table(db, sql, &resultp, &nrow, &ncloumn, &errmsg);
if(nrow == 1)
{
strcpy(msg->data,"huchi");
msg->sign = 0; //代表操作失败发送失败信息
return -1;
}
//没找到说明没有人操作这个数据,将no置1
if(nrow == 0)
{
sprintf(sql,"update book1 set no = 1 where name = '%s' ",msg->user.name);
//上锁
sqlite3_exec(db,sql,NULL,NULL,&errmsg);
}
return 0;
}
/**********************************
*互斥解锁
***********************************/
int mutex_after(MSG *msg,sqlite3 *db)
{
char * errmsg;
char sql[521];
sprintf(sql,"update book1 set no = 0 where name = '%s' ",msg->user.name);
sqlite3_exec(db,sql,NULL,NULL,&errmsg);
return 0;
}