项目需求:
1)服务器负责管理所有员工表单(以数据库形式),其他客户端可通过网络连接服务器来查询员工表单。
2)需要账号密码登陆,其中需要区分管理员账号还是普通用户账号。
3)管理员账号可以查看、修改、添加、删除员工信息,同时具有查询历史记录功能,管理员要负责管理所有的普通用户。
4)普通用户只能查询修改与本人有关的相关信息,其他员工信息不得查看修改。
5)服务器能同时相应多台客户端的请求功能。
服务器流程图:
客户端流程图:
服务器端:
ser.c :
#include <stdio.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include "seropt.h"
#define MAX 1024
#define PRT_ERR(msg) \
do \
{ \
perror(msg); \
exit(-1); \
}while (0)
msg_t info;
int main(int argc, char const *argv[])
{
if(argc!=3){ //外部传参个数判断
fprintf(stderr, "Format Error:%s <ip> <port>\n", argv[0]);
exit(-1);
}
//创建数据库
//create_db();
int sfd = socket(AF_INET, SOCK_STREAM, 0); //创建TCP套接字
if (sfd < 0)
PRT_ERR("socket error");
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0) //设置端口快速复用
PRT_ERR("setsockopt error");
struct sockaddr_in ser_addr; //保存服务器地址信息结构体
struct sockaddr_in cli_addr; //保存客户端地址信息结构体
struct sockaddr_in addrs[MAX] = {0}; //用于备份客户端地址信息
socklen_t addr_len = sizeof(struct sockaddr_in);
ser_addr.sin_family = AF_INET; // 填充服务器地址信息结构体
ser_addr.sin_addr.s_addr = inet_addr(argv[1]); //点分十进制字符串转换为ip值
ser_addr.sin_port = htons(atoi(argv[2])); //字符串转化为数值,并转化为大端存储
if(bind(sfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr))<0) //绑定服务器地址信息
PRT_ERR("bind error");
if(listen(sfd,5)<0) //监听客户端连接
PRT_ERR("listen error");
int epfd=epoll_create(1); //创建epoll
if(epfd<0)
PRT_ERR("epoll_create error");
struct epoll_event event;
struct epoll_event revent[MAX]={0};
event.data.fd = sfd;
event.events = EPOLLIN;
if(epoll_ctl(epfd,EPOLL_CTL_ADD,sfd,&event)<0) //将客户端连接事件加入epoll要监听的成员中
PRT_ERR("epoll_ctl error");
int count=0,ret=0;
int cfd;
int i;
char from[24];
msg_t info;
while (1){
count = epoll_wait(epfd, revent, MAX, -1); // epoll开启监听,不需要考虑超时时间
if(count<0){
PRT_ERR("epoll_wait error");
}else{
for (i = 0; i < count;i++){
if(revent[i].data.fd==sfd){
//客户端发来连接请求
cfd=accept(sfd,(struct sockaddr *)&cli_addr,&addr_len);
if(cfd<0)
PRT_ERR("accept error");
printf("%s:%d 连接服务器\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
addrs[cfd] = cli_addr; //备份客户端信息
event.data.fd = cfd;
event.events = EPOLLIN;
if(epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &event) < 0)
PRT_ERR("epoll_ctl error");
}else{
//客户端发来消息
cfd = revent[i].data.fd;
ret=recvMsg(cfd, &info,sizeof(info));
if(ret<0){
PRT_ERR("recv error");
exit(-1);
}else if(ret==0){
//客户端断开连接
printf("%s:%d 断开服务器连接\n", inet_ntoa(addrs[cfd].sin_addr),\
ntohs(addrs[cfd].sin_port));
event.data.fd = cfd;
event.events = EPOLLIN;
if(epoll_ctl(epfd, EPOLL_CTL_DEL, cfd, &event) < 0) //从监听成员中删除
PRT_ERR("epoll_ctl error");
}else{
bzero(from,sizeof(from));
sprintf(from,"%s:%d",inet_ntoa(addrs[cfd].sin_addr),\
ntohs(addrs[cfd].sin_port));
switch(info.msgtype){
case 'd':
deal_login_irq(cfd, &info,sizeof(info));
break;
case 't':
deal_add_req(cfd,&info,sizeof(info),from);
break;
case 'c':
deal_inquire_req(cfd,&info,sizeof(info),from);
break;
case 's':
deal_delte_req(cfd,&info,sizeof(info),from);
break;
case 'l':
deal_inquire_history_req(cfd,&info,sizeof(info),from);
break;
case 'g':
deal_update_req(cfd,&info,sizeof(info),from);
break;
}
memset(&info, 0, sizeof(info));
}
}
}
}
}
return 0;
}
seropt.c :
#include "seropt.h"
//创建数据库
void create_db()
{
char buf[SIZE];
char *errmsg = NULL;
sqlite3 *db = NULL;
if(sqlite3_open("./staff_sys.db",&db)!=SQLITE_OK){
printf("sqlite3_open error:%s\n", sqlite3_errmsg(db));
return ;
}
//创建用于保存员工信息的表
bzero(buf, sizeof(buf));
sprintf(buf, "create table if not exists userinfo (root char,id int primary key,name char,passwd char,age int,tel char,addr char,work char,time char,level int,salary double)");
if(sqlite3_exec(db,buf,NULL,NULL,&errmsg)!=SQLITE_OK){
printf("sqlite3_exec error:%s\n", errmsg);
return ;
}
//创建记录历史信息的表
bzero(buf, sizeof(buf));
sprintf(buf, "create table if not exists history (ip char,time char,user char,opertaion char)");
if(sqlite3_exec(db,buf,NULL,NULL,&errmsg)!=SQLITE_OK){
printf("sqlite3_exec error:%s\n", errmsg);
return ;
}
//插入默认管理员用户
bzero(buf, sizeof(buf));
sprintf(buf, "insert into userinfo values ('root',1000,'admin','admin123',18,'13850816501','华清远见上海中心','系统管理员','2023.02.23',5,10000)");
if(sqlite3_exec(db,buf,NULL,NULL,&errmsg)!=SQLITE_OK){
printf("sqlite3_exec error:%s\n", errmsg);
return ;
}
sqlite3_close(db);
}
//插入一条历史操作信息
int insert_history_info(char *from,char *who,char *what)
{
time_t sec = 0;
char buf[SIZE];
char date[32]={0};
char *errmsg = NULL;
sqlite3 *db = NULL;
struct tm *tm;
if(sqlite3_open("./staff_sys.db",&db)!=SQLITE_OK){
printf("sqlite3_open error:%s\n", sqlite3_errmsg(db));
return -1;
}
time(&sec);
tm = localtime(&sec);
sprintf(date,"%04d-%02d-%02d %02d:%02d:%02d",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,\
tm->tm_hour,tm->tm_min,tm->tm_sec);
//插入操作信息
bzero(buf, sizeof(buf));
sprintf(buf, "insert into history values ('%s','%s','%s','%s')",\
from,date,who,what);
if(sqlite3_exec(db,buf,NULL,NULL,&errmsg)!=SQLITE_OK){
printf("sqlite3_exec error:%s\n", errmsg);
return -1;
}
sqlite3_close(db);
return 0;
}
//插入新员工数据
int insert_info(msg_t *info)
{
char buf[SIZE];
char *errmsg = NULL;
sqlite3 *db = NULL;
if(sqlite3_open("./staff_sys.db",&db)!=SQLITE_OK){
printf("sqlite3_open error:%s\n", sqlite3_errmsg(db));
return -1;
}
//插入员工信息
bzero(buf, sizeof(buf));
if(!info->root){
sprintf(buf, "insert into userinfo values ('root',%d,'%s','%s',%d,'%s','%s','%s','%s',%d,%lf)",\
info->staff.id,info->staff.name,info->staff.passwd,info->staff.age,info->staff.tel,\
info->staff.addr,info->staff.work,info->staff.time,info->staff.level,info->staff.salary);
}else{
sprintf(buf, "insert into userinfo values ('consumer',%d,'%s','%s',%d,'%s','%s','%s','%s',%d,%lf)",\
info->staff.id,info->staff.name,info->staff.passwd,info->staff.age,info->staff.tel,\
info->staff.addr,info->staff.work,info->staff.time,info->staff.level,info->staff.salary);
}
if(sqlite3_exec(db,buf,NULL,NULL,&errmsg)!=SQLITE_OK){
printf("sqlite3_exec error:%s\n", errmsg);
return -1;
}
sqlite3_close(db);
return 0;
}
//删除员工信息
int delete_info(msg_t *info)
{
char buf[SIZE];
char *errmsg = NULL;
sqlite3 *db = NULL;
if(sqlite3_open("./staff_sys.db",&db)!=SQLITE_OK){
printf("sqlite3_open error:%s\n", sqlite3_errmsg(db));
return -1;
}
//删除员工信息
bzero(buf, sizeof(buf));
sprintf(buf, "delete from userinfo where id='%d' and name = '%s'",\
info->staff.id,info->staff.name);
if(sqlite3_exec(db,buf,NULL,NULL,&errmsg)!=SQLITE_OK){
printf("sqlite3_exec error:%s\n", errmsg);
return -1;
}
sqlite3_close(db);
return 0;
}
//查询用户信息
int inquire_info(int fd,msg_t *info,int flag,int size)
{
char buf[SIZE];
char *errmsg = NULL;
sqlite3 *db = NULL;
char **restr=NULL;
int row=0;
int column=0;
int temp=-1;
if(sqlite3_open("./staff_sys.db",&db)!=SQLITE_OK){
printf("sqlite3_open error:%s\n", sqlite3_errmsg(db));
return -1;
}
switch(flag){
case 0:
bzero(buf, sizeof(buf));
sprintf(buf,"select * from userinfo");
if(sqlite3_get_table(db,buf,&restr,&row,&column,&errmsg)!=SQLITE_OK){
printf("sqlite3_get_table error:%s\n", sqlite3_errmsg(db));
return -1;
}
if(row>=1){
for(int i=0;i<column*(row+1);i++){
strcpy(info->str, restr[i]);
sendMsg(fd,info,size);
}
temp = info->usertype;
info->usertype = -1;
sendMsg(fd,info,size);
info->usertype = temp;
}else{
info->usertype = -2;
sendMsg(fd,info,size);
}
break;
case 2:
case 1:
bzero(buf, sizeof(buf));
sprintf(buf,"select * from userinfo where name='%s'",info->staff.name);
if(sqlite3_get_table(db,buf,&restr,&row,&column,&errmsg)!=SQLITE_OK){
printf("sqlite3_get_table error:%s\n", sqlite3_errmsg(db));
return -1;
}
if(row>=1){
for(int i=0;i<column*(row+1);i++){
strcpy(info->str, restr[i]);
sendMsg(fd,info,size);
}
temp = info->usertype;
info->usertype = -1;
sendMsg(fd,info,size);
info->usertype = temp;
}else{
info->usertype = -2;
sendMsg(fd,info,size);
}
break;
}
sqlite3_free_table(restr);
sqlite3_close(db);
return 0;
}
//查询历史记录
int inquire_history_info(int fd,msg_t *info,int size)
{
char buf[SIZE];
char *errmsg = NULL;
sqlite3 *db = NULL;
char **restr=NULL;
int row=0;
int column=0;
int temp=-1;
if(sqlite3_open("./staff_sys.db",&db)!=SQLITE_OK){
printf("sqlite3_open error:%s\n", sqlite3_errmsg(db));
return -1;
}
bzero(buf, sizeof(buf));
sprintf(buf,"select * from history");
if(sqlite3_get_table(db,buf,&restr,&row,&column,&errmsg)!=SQLITE_OK){
printf("sqlite3_get_table error:%s\n", sqlite3_errmsg(db));
return -1;
}
if(row>=1){
for(int i=0;i<column*(row+1);i++){
strcpy(info->str, restr[i]);
sendMsg(fd,info,size);
}
temp = info->usertype;
info->usertype = -1;
sendMsg(fd,info,size);
info->usertype = temp;
}else{
info->usertype = -2;
sendMsg(fd,info,size);
}
sqlite3_free_table(restr);
sqlite3_close(db);
return 0;
}
//修改员工信息
int update_info(int id,char *text,char *str,int value)
{
char buf[SIZE];
char *errmsg = NULL;
sqlite3 *db = NULL;
if(sqlite3_open("./staff_sys.db",&db)!=SQLITE_OK){
printf("sqlite3_open error:%s\n", sqlite3_errmsg(db));
return -1;
}
bzero(buf, sizeof(buf));
if(str!=NULL){
sprintf(buf, "update userinfo set '%s' = '%s' where id = '%d'",text,str,id);
if(sqlite3_exec(db,buf,NULL,NULL,&errmsg)!=SQLITE_OK){
printf("sqlite3_exec error:%s\n", errmsg);
return -1;
}
}else{
if(strcmp(text,"salary")==0)
sprintf(buf, "update userinfo set '%s' = '%lf' where id = '%d'",text,(double)value,id);
else
sprintf(buf, "update userinfo set '%s' = '%d' where id = '%d'",text,value,id);
if(sqlite3_exec(db,buf,NULL,NULL,&errmsg)!=SQLITE_OK){
printf("sqlite3_exec error:%s\n", errmsg);
return -1;
}
}
sqlite3_close(db);
return 0;
}
//处理登录请求
int deal_login_irq(int fd,msg_t *info,int size)
{
char buf[SIZE];
char *errmsg = NULL;
sqlite3 *db = NULL;
char **restr=NULL;
int row=0;
int column=0;
if(sqlite3_open("./staff_sys.db",&db)!=SQLITE_OK){
printf("sqlite3_open error:%s\n", sqlite3_errmsg(db));
return -1;
}
bzero(buf, sizeof(buf));
sprintf(buf,"select * from userinfo where name=\"%s\"",info->staff.name);
if(sqlite3_get_table(db,buf,&restr,&row,&column,&errmsg)!=SQLITE_OK){
printf("sqlite3_get_table error:%s\n", sqlite3_errmsg(db));
return -1;
}
if(row==0){
sprintf(info->str, "用户名不存在");
}else{
for (int i = 1; i <= row;i++){
if(strcmp(restr[i*column+3],info->staff.passwd)==0){
if(!info->usertype){
if(strcmp(restr[i*column],"root")==0){
strcpy(info->str, "login success");
}else{
sprintf(info->str, "用户%s非管理员", restr[i * column + 3]);
}
}else{
if(strcmp(restr[i*column],"consumer")==0){
info->staff.id = atoi(restr[i*column+1]);
strcpy(info->str, "login success");
}else{
sprintf(info->str, "用户%s为管理员", restr[i * column + 3]);
}
}
}else{
strcpy(info->str, "密码错误");
}
}
}
sendMsg(fd, info, size);
sqlite3_free_table(restr);
sqlite3_close(db);
return 0;
}
//处理添加新员工请求
int deal_add_req(int fd,msg_t *info,int size,char *from)
{
char buf[BUFSIZE];
if(insert_info(info)<0){
strcpy(info->str, "add failed");
}else{
strcpy(info->str, "add success");
bzero(buf, sizeof(buf));
sprintf(buf, "管理员添加了员工%s的信息", info->staff.name);
insert_history_info(from,"管理员", buf);
}
sendMsg(fd, info, size);
return 0;
}
//处理查询用户信息请求
int deal_inquire_req(int fd,msg_t *info,int size,char *from)
{
char buf[BUFSIZE];
bzero(buf, sizeof(buf));
inquire_info(fd, info, info->usertype, size);
switch(info->usertype){
case 0:
insert_history_info(from,"管理员","管理员查询了所有员工信息");
break;
case 1:
sprintf(buf, "管理员查询了员工%s的信息", info->staff.name);
insert_history_info(from,"管理员", buf);
break;
case 2:
sprintf(buf, "员工%s进行信息查询", info->staff.name);
insert_history_info(from,info->staff.name, buf);
break;
}
return 0;
}
//处理删除员工信息请求
int deal_delte_req(int fd, msg_t *info, int size,char *from)
{
char buf[BUFSIZE];
if(delete_info(info)<0){
strcpy(info->str, "delete failed");
}else{
strcpy(info->str, "delete success");
bzero(buf, sizeof(buf));
sprintf(buf, "管理员删除了工号为%d的员工信息", info->staff.id);
insert_history_info(from,"管理员", buf);
}
sendMsg(fd, info, size);
return 0;
}
//处理查询历史记录信息请求
int deal_inquire_history_req(int fd, msg_t *info, int size,char *from)
{
insert_history_info(from,"管理员","管理员查询了历史记录信息");
inquire_history_info(fd, info, size);
return 0;
}
//处理修改信息请求
int deal_update_req(int fd,msg_t *info,int size,char *from)
{
char buf[SIZE];
char what[BUFSIZE];
char who[NAMELEN];
char uname[NAMELEN];
char *errmsg = NULL;
sqlite3 *db = NULL;
char **restr=NULL;
int row=0;
int column=0;
int flag = 0;
if(sqlite3_open("./staff_sys.db",&db)!=SQLITE_OK){
printf("sqlite3_open error:%s\n", sqlite3_errmsg(db));
return -1;
}
bzero(buf, sizeof(buf));
bzero(uname, sizeof(uname));
bzero(what, sizeof(what));
bzero(who, sizeof(who));
sprintf(buf, "select * from userinfo where id = '%d'", info->staff.id);
if(sqlite3_get_table(db,buf,&restr,&row,&column,&errmsg)!=SQLITE_OK){
printf("sqlite3_get_table error:%s\n", sqlite3_errmsg(db));
return -1;
}
if(row<1){
strcpy(info->str,"用户名不存在");
sendMsg(fd,info,size);
sqlite3_free_table(restr);
sqlite3_close(db);
return -1;
}else{
strcpy(uname, restr[column + 2]);
}
sqlite3_free_table(restr);
sqlite3_close(db);
if(strcmp(info->str,"root")==0){
flag = 1;
strcpy(who, "管理员");
}else{
strcpy(who, uname);
}
switch(info->usertype){
case 1:
update_info(info->staff.id,"name",info->staff.name,0);
if(flag)
sprintf(what,"管理员修改了%s的名字信息",uname);
else
sprintf(what, "员工%s修改了名字信息", uname);
break;
case 2:
update_info(info->staff.id,"age",NULL,info->staff.age);
if(flag)
sprintf(what,"管理员修改了%s的年龄信息",uname);
else
sprintf(what, "员工%s修改了年龄信息", uname);
break;
case 3:
update_info(info->staff.id,"addr",info->staff.addr,0);
if(flag)
sprintf(what,"管理员修改了%s的地址信息",uname);
else
sprintf(what, "员工%s修改了地址信息", uname);
break;
case 4:
update_info(info->staff.id,"tel",info->staff.tel,0);
if(flag)
sprintf(what,"管理员修改了%s的电话信息",uname);
else
sprintf(what, "员工%s修改了电话信息", uname);
break;
case 5:
update_info(info->staff.id,"work",info->staff.work,0);
sprintf(what,"管理员修改了%s的职位信息",uname);
break;
case 6:
update_info(info->staff.id,"salary",NULL,info->staff.salary);
sprintf(what,"管理员修改了%s的薪资信息",uname);
break;
case 7:
update_info(info->staff.id,"time",info->staff.time,0);
sprintf(what,"管理员修改了%s的入职时间信息",uname);
break;
case 8:
update_info(info->staff.id,"level",NULL,info->staff.level);
sprintf(what,"管理员修改了%s的评级信息",uname);
break;
case 9:
update_info(info->staff.id,"passwd",info->staff.passwd,0);
if(flag)
sprintf(what,"管理员修改了%s的密码信息",uname);
else
sprintf(what, "员工%s修改了密码信息", uname);
break;
}
insert_history_info(from,who,what);
strcpy(info->str,"update success");
sendMsg(fd,info,size);
}
客户端:
cli.c :
#include <stdio.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include "cliopt.h"
#define PRT_ERR(msg) \
do \
{ \
perror(msg); \
exit(-1); \
}while (0)
int main(int argc, char const *argv[])
{
if(argc!=3){ //外部传参个数判断
fprintf(stderr, "Format Error:%s <ip> <port>\n", argv[0]);
exit(-1);
}
int cfd = socket(AF_INET, SOCK_STREAM, 0); //创建TCP套接字
if (cfd < 0)
PRT_ERR("socket error");
struct sockaddr_in ser_addr; //保存服务器地址信息结构体
ser_addr.sin_family = AF_INET; //填充服务器地址信息结构体
ser_addr.sin_addr.s_addr = inet_addr(argv[1]); //点分十进制字符串转换为ip值
ser_addr.sin_port = htons(atoi(argv[2])); //字符串转化为数值,并转化为大端存储
if(connect(cfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr))<0) //连接服务器
PRT_ERR("connect error");
int ret = 0;
int which;
char name[NAMELEN]={0};
int id=-1;
while (1){
select_interface();
wait_input_int(&which);
switch(which){
case 1:
ret=send_login_req(cfd, 0,NULL,0);
if(ret){
root_interface(cfd);
}
break;
case 2:
ret=send_login_req(cfd, 1,name,&id);
if(ret){
user_interface(cfd,name,id);
}
break;
case 3:
exit(0);
break;
default:
printf("选择有误,请重试!\n");
break;
}
}
return 0;
}
cliopt.c :
#include "cliopt.h"
//定义消息
msg_t info;
//界面打印
void select_interface()
{
puts("***************************************************");
puts("********1.管理员登录 2.员工登录 3.退出*********");
puts("***************************************************");
printf("请输入>>>");
fflush(stdout);
}
void inquire_interface(int cfd)
{
int which;
while(1){
puts("***************************************************");
puts("********1.按名字查询 2.查询所有 3.退出*********");
puts("***************************************************");
printf("请输入>>>");
fflush(stdout);
wait_input_int(&which);
switch(which){
case 1:
send_inquire_req(cfd, 0, NULL);
break;
case 2:
send_inquire_req(cfd, 1, NULL);
break;
case 3:
return;
default:
printf("选择有误,请重试!\n");
break;
}
}
}
void root_interface(int cfd)
{
int which;
while(1){
puts("********************************************************************");
puts("***1.查询 2.修改 3.添加用户 4.删除用户 5.查询历史记录 6.退出***");
puts("********************************************************************");
printf("请输入>>>");
fflush(stdout);
wait_input_int(&which);
switch(which){
case 1:
inquire_interface(cfd);
break;
case 2:
root_update_interface(cfd);
break;
case 3:
send_add_req(cfd,0);
break;
case 4:
send_delete_req(cfd,0);
break;
case 5:
sned_inquire_history_req(cfd);
break;
case 6:
return ;
default:
printf("选择有误,请重试!\n");
break;
}
}
}
void user_interface(int cfd,char *name,int id)
{
int which;
while(1){
puts("*************************************************");
puts("************1.查询 2.修改 3.退出*************");
puts("*************************************************");
printf("请输入>>>");
fflush(stdout);
wait_input_int(&which);
switch(which){
case 1:
send_inquire_req(cfd, 0, name);
break;
case 2:
user_update_interface(cfd, id);
break;
case 3:
return;
default:
printf("选择有误,请重试!\n");
break;
}
}
}
void root_update_interface(int cfd)
{
int which;
int id = -1;
printf("请输入要修改信息的员工工号>>>");
fflush(stdout);
wait_input_int(&id);
while(1){
puts("********************请输入要修改的选项***************************");
puts("************1.姓名 2.年龄 3.常住地址 4.电话****************");
puts("************5.职位 6.工资 7.入职年月 8.评级****************");
puts("************9.密码 10.退出 *****************");
puts("*****************************************************************");
printf("请输入>>>");
fflush(stdout);
wait_input_int(&which);
if(which<1 && which>10){
printf("选择有误,请重试!\n");
continue;
}
send_update_req(cfd,id,which,0);
break;
}
}
void user_update_interface(int cfd,int id)
{
int which;
while(1){
puts("********************请输入要修改的选项***************************");
puts("************1.姓名 2.年龄 3.常住地址 4.电话****************");
puts("************5.密码 6.退出 ******************");
puts("*****************************************************************");
printf("请输入>>>");
fflush(stdout);
wait_input_int(&which);
if(which<1 && which>6){
printf("选择有误,请重试!\n");
continue;
}else if(which==5 || which==6){
which += 4;
}
send_update_req(cfd, id, which,1);
break;
}
}
//操作方法
void wait_input_int(int *value)
{
int ret;
while (1){
ret=scanf("%d",value);
if(ret!=1){
printf("输入有误,请重试!\n");
printf("请输入>>>");
while(getchar()!='\n');
}else{
break;
}
}
while(getchar()!='\n');
}
void wait_input_double(double *value)
{
int ret;
while (1){
ret=scanf("%lf",value);
if(ret!=1){
printf("输入有误,请重试!\n");
printf("请输入>>>");
while(getchar()!='\n');
}else{
break;
}
}
while(getchar()!='\n');
}
void wait_input_str(char *str,int len)
{
fgets(str, len, stdin);
str[strlen(str) - 1] = '\0';
}
//发送登录请求
int send_login_req(int cfd,int flag,char *name,int *id) //flag=0,表示管理员请求登录,name用于保留员工用户名
{
int ret = 0;
memset(&info, 0, sizeof(info));
puts("********管理员/用户登录********");
printf("请输入用户名>>>");
fflush(stdout);
wait_input_str(info.staff.name,sizeof(info.staff.name));
printf("请输入密码>>>");
fflush(stdout);
wait_input_str(info.staff.passwd,sizeof(info.staff.passwd));
info.msgtype = 'd'; //登录信息标识
info.usertype = flag;
ret=sendMsg(cfd, &info, sizeof(info));
if(ret!=sizeof(info)){
printf("发送登录请求失败\n");
return -1;
}
if(recvMsg(cfd,&info,sizeof(info))==0){
printf("断开连接\n");
exit(-1);
}
if(strcmp(info.str,"login success")==0){
if(name!=NULL){
strcpy(name, info.staff.name);
*id = info.staff.id;
}
printf("登录成功\n");
return 1;
}else{
printf("登录失败,%s,请重试!\n", info.str);
return 0;
}
}
//发送添加请求
int send_add_req(int cfd,int flag) //flag=0,表示管理员
{
int ret = 0;
memset(&info, 0, sizeof(info));
printf("请输入工号>>>");
fflush(stdout);
wait_input_int(&info.staff.id);
printf("请输入用户名>>>");
fflush(stdout);
wait_input_str(info.staff.name,sizeof(info.staff.name));
printf("请输入密码>>>");
fflush(stdout);
wait_input_str(info.staff.passwd,sizeof(info.staff.passwd));
printf("请输入年龄>>>");
fflush(stdout);
wait_input_int(&info.staff.age);
printf("请输入联系电话>>>");
fflush(stdout);
wait_input_str(info.staff.tel,sizeof(info.staff.tel));
printf("请输入常住地址>>>");
fflush(stdout);
wait_input_str(info.staff.addr,sizeof(info.staff.addr));
printf("请输入员工职位>>>");
fflush(stdout);
wait_input_str(info.staff.work,sizeof(info.staff.work));
printf("请输入员工入职时间>>>");
fflush(stdout);
wait_input_str(info.staff.time,sizeof(info.staff.time));
printf("请输入职位级别(1-5)>>>");
fflush(stdout);
wait_input_int(&info.staff.level);
printf("请输入员工月薪>>>");
fflush(stdout);
wait_input_double(&info.staff.salary);
printf("是否赋予管理员权限(yes:0 no:1)>>>");
fflush(stdout);
wait_input_int(&info.root);
info.msgtype = 't'; //添加信息标识
info.usertype = flag;
ret=sendMsg(cfd, &info, sizeof(info));
if(ret!=sizeof(info)){
printf("发送添加请求失败\n");
return -1;
}
if(recvMsg(cfd,&info,sizeof(info))==0){
printf("断开连接\n");
exit(-1);
}
if(strcmp(info.str,"add success")==0){
printf("添加成功\n");
return 1;
}else{
printf("添加失败,请重试!\n");
return 0;
}
}
//发送查询请求
int send_inquire_req(int cfd,int flag,char *name) //flag为1表示查询所有用户信息,为0表示查询单个用户信息
{
int ret=0;
int i;
memset(&info, 0, sizeof(info));
info.msgtype = 'c'; //添加信息标识
info.usertype=0; //查询所有信息
if(!flag){
if(name==NULL){
printf("请输入要查询的用户名>>>");
fflush(stdout);
wait_input_str(info.staff.name,sizeof(info.staff.name));
info.usertype=1; //查询指定用户信息
}else{
strcpy(info.staff.name, name);
info.usertype = 2; //员工查询
}
}
ret=sendMsg(cfd, &info, sizeof(info));
if(ret!=sizeof(info)){
printf("发送添加请求失败\n");
return -1;
}
i=0;
while(1){
if(recvMsg(cfd,&info,sizeof(info))==0){
printf("断开连接\n");
exit(-1);
}
if(info.usertype==-1){
printf("查询完毕\n");
break;
}else if(info.usertype==-2){
printf("查询失败,请重试!\n");
break;
}
i++;
printf("%s",info.str);
if(i%11==0)
putchar('\n');
else
putchar('\t');
}
return 0;
}
//发送删除用户请求
int send_delete_req(int cfd, int flag) //flag=0,表示管理员
{
int ret = 0;
memset(&info, 0, sizeof(info));
memset(&info, 0, sizeof(info));
printf("请输入要删除员工信息的工号>>>");
fflush(stdout);
wait_input_int(&info.staff.id);
printf("请输入要删除员工信息的用户名>>>");
fflush(stdout);
wait_input_str(info.staff.name,sizeof(info.staff.name));
info.msgtype = 's'; //添加信息标识
info.usertype = flag;
ret=sendMsg(cfd, &info, sizeof(info));
if(ret!=sizeof(info)){
printf("发送删除请求失败\n");
return -1;
}
if(recvMsg(cfd,&info,sizeof(info))==0){
printf("断开连接\n");
exit(-1);
}
if(strcmp(info.str,"delete success")==0){
printf("删除成功\n");
return 1;
}else{
printf("删除失败,请重试!\n");
return 0;
}
return 0;
}
//发送查询历史记录请求
int sned_inquire_history_req(int cfd)
{
int ret=0;
int i;
memset(&info, 0, sizeof(info));
info.msgtype = 'l'; //查询历史记录信息标识
ret=sendMsg(cfd, &info, sizeof(info));
if(ret!=sizeof(info)){
printf("发送添加请求失败\n");
return -1;
}
i=0;
while(1){
if(recvMsg(cfd,&info,sizeof(info))==0){
printf("断开连接\n");
exit(-1);
}
if(info.usertype==-1){
printf("查询完毕\n");
break;
}else if(info.usertype==-2){
printf("查询失败,请重试!\n");
break;
}
i++;
printf("%s",info.str);
if(i%4==0)
putchar('\n');
else
putchar('\t');
}
return 0;
}
//发送修改信息请求
int send_update_req(int cfd,int id,int which,int flag)
{
int ret=0;
int i;
memset(&info, 0, sizeof(info));
info.msgtype = 'g'; //修改信息标识
info.staff.id = id;
info.usertype = which;
if(!flag)
strcpy(info.str, "root");
else
strcpy(info.str, "consumer");
switch(which){
case 1:
printf("请输入新的用户名>>>");
fflush(stdout);
wait_input_str(info.staff.name,sizeof(info.staff.name));
break;
case 2:
printf("请输入新的年龄>>>");
fflush(stdout);
wait_input_int(&info.staff.age);
break;
case 3:
printf("请输入新的常住地址>>>");
fflush(stdout);
wait_input_str(info.staff.addr,sizeof(info.staff.addr));
break;
case 4:
printf("请输入新的电话号码>>>");
fflush(stdout);
wait_input_str(info.staff.tel,sizeof(info.staff.tel));
break;
case 5:
printf("请输入新的职位>>>");
fflush(stdout);
wait_input_str(info.staff.work,sizeof(info.staff.work));
break;
case 6:
printf("请输入新的月薪>>>");
fflush(stdout);
wait_input_double(&info.staff.salary);
break;
case 7:
printf("请输入新的入职年月>>>");
fflush(stdout);
wait_input_str(info.staff.time,sizeof(info.staff.time));
break;
case 8:
printf("请输入新的评级>>>");
fflush(stdout);
wait_input_int(&info.staff.level);
break;
case 9:
printf("请输入新的密码>>>");
fflush(stdout);
wait_input_str(info.staff.passwd,sizeof(info.staff.passwd));
break;
case 10:
memset(&info,0,sizeof(info));
return 0;
}
ret=sendMsg(cfd, &info, sizeof(info));
if(ret!=sizeof(info)){
printf("发送修改请求失败\n");
return -1;
}
if(recvMsg(cfd,&info,sizeof(info))==0){
printf("断开连接\n");
exit(-1);
}
if(strcmp(info.str,"update success")==0){
printf("修改成功\n");
return 1;
}else{
printf("修改失败,%s,请重试!\n",info.str);
return 0;
}
return 0;
}
共用 头文件和功能函数:
common.h :
#ifndef __COMMON_H__
#define __COMMON_H__
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#define NAMELEN 24
#define PASSWDLEN 16
#define TELLEN 16
#define ADDRLEN 32
#define WORKLEN 32
#define TIMELEN 16
#define BUFSIZE 64
#pragma pack(1)
//用于保存员工信息的结构体
typedef struct staff_info {
int id;
char name[NAMELEN];
char passwd[PASSWDLEN];
int age;
char tel[TELLEN];
char addr[ADDRLEN];
char work[WORKLEN];
char time[TIMELEN];
int level;
double salary;
}staff_t;
//用于服务器与客户端通信的消息结构体
typedef struct {
int msgtype;
int usertype;
int root;
char str[BUFSIZE];
staff_t staff;
} msg_t;
#pragma pack()
//减少TCP的粘包问题
int sendMsg(int fd, msg_t *msg, int size);
int recvMsg(int fd, msg_t *msg, int size);
#endif
common.c :
#include "common.h"
//发送指定大小数据
int sendMsg(int fd, msg_t *msg, int size)
{
char *buf=(char *)msg;
int count=size;
int len=0;
while(count>0){
len=send(fd,buf,count,0);
if(len<0){
return -1;
}
buf+=len;
count-=len;
}
return size;
}
//接受指定大小数据
int recvMsg(int fd, msg_t *msg, int size)
{
char *buf=(char *)msg;
int count=size;
int len=0;
while(count>0){
len=recv(fd,buf,count,0);
if(len<0){
return -1;
}else if(0==len){
return 0;
}
buf+=len;
count-=len;
}
return size;
}