头文件common.h
#ifndef __COMMON_H__
#define __COMMON_H__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 256 //字符数组容量
//打印错误信息
#define ERR_MSG(msg) do{\
fprintf(stderr, " __%d__ ", __LINE__);\
perror(msg);\
}while(0)
//获取当前时间日期
struct tm* getTime();
//员工信息包
typedef struct
{
int cmd; // 功能码
int id; // 工号
int age; // 年龄
char name[50]; // 名字
char sex; // 性别
char department[20]; // 部门
char phone[12]; // 手机号
char passwd[50]; // 密码
}Msg_t;
//功能码
enum CMD
{
ROOT_LOGIN, //管理员登录
USER_LOGIN, //用户登录
ADD_USER, //添加用户
DEL_USER, //删除用户
UPDATE_NAME, //更新名字
UPDATE_AGE, //更新年龄
UPDATE_SEX, //更新性别
UPDATE_DEPARTMENT, //更新部门
UPDATE_PHONE, //更新号码
UPDATE_PASSWD, //更新密码
FIND_ALL, //查询所有用户信息
FIND_ID, //查询对应工号信息
HISTORY, //查看历史记录
};
//回收僵尸进程
void handler(int sig);
//判断管理员或用户输入的账号密码是否正确
int isLogin(Msg_t user, sqlite3* db, int newfd);
//管理员添加用户
int rootAddUser(Msg_t user, sqlite3* db, int newfd);
//管理员删除用户
int rootDelUser(Msg_t user, sqlite3* db, int newfd);
//更新用户信息
int rootUpdate(Msg_t user, sqlite3* db, int newfd);
//查询用户信息
int rootFind(Msg_t user, sqlite3* db, int newfd);
//查询历史数据
int rootHistory(Msg_t user, sqlite3* db, int newfd);
//登录菜单
unsigned int loginMenu();
//输入账号密码
Msg_t login(Msg_t user, int cmd);
//管理员菜单
unsigned int rootMenu();
//请求添加用户
int addUser(int sfd, Msg_t user);
//请求删除用户
int deleteUser(int sfd,Msg_t user);
//请求更新数据
int updateUser(int sfd, Msg_t user);
//请求查询用户信息
int findUser(int sfd, Msg_t user);
//请求查询历史操作记录
int history(int sfd, Msg_t user);
//普通用户菜单
unsigned int generalMenu();
#endif
功能文件 common.c
#include "./common.h"
//回收僵尸进程
void handler(int sig)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
return;
}
//获取当前时间日期
struct tm* getTime()
{
time_t t = time(NULL);
struct tm* nowtime = NULL;
nowtime = localtime(&t);
//如果时间获取失败就重新获取
while(nowtime == NULL)
{
t = time(NULL);
nowtime = localtime(&t);
}
return nowtime;
}
//判断管理员或用户输入的账号密码是否正确
int isLogin(Msg_t user, sqlite3* db, int newfd)
{
char sql[MAX]="";
sprintf(sql, "select * from staffMessage where id=%d;",user.id);
char** buf;
int row;
int column;
if(sqlite3_get_table(db, sql, &buf, &row, &column, NULL)!= SQLITE_OK)
{
printf("查询失败\n");
return -1;
}
if(buf[7]==NULL)//无该账号
{
strcpy(sql, "id error");
}else if((atoi(buf[7])==user.id) && (strcmp(buf[13],user.passwd)==0))//账号密码正确
{
strcpy(sql, "success");
}else
{
strcpy(sql, "password error");//密码错误
}
//发送反馈信息
if(send(newfd, sql, sizeof(sql), 0) < 0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
//管理员添加用户
int rootAddUser(Msg_t user, sqlite3* db, int newfd)
{
char sql[MAX]="";
sprintf(sql, "insert into staffMessage values (%d,\"%s\",%d,'%c',\"%s\",\"%s\",\"%s\");",
user.id,user.name,user.age,user.sex,user.department,user.phone,user.passwd);
if(sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK)
{
printf("添加用户失败\n");
strcpy(sql,"添加失败");//反馈信息
}else
{
printf("添加用户成功\n");
//插入操作记录
struct tm *time = getTime();
sprintf(sql, "insert into history values (\"添加新用户 ID:%d\",\"%d/%d/%d %d:%d\",1234);", user.id,time->tm_year+1900,time->tm_mon+1,time->tm_mday,time->tm_hour,time->tm_min);
if(sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK)
{
printf("添加记录失败\n");
return -1;
}
strcpy(sql,"添加成功");//反馈信息
}
//发送反馈信息
if(send(newfd, sql, sizeof(sql), 0) < 0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
//管理员删除用户
int rootDelUser(Msg_t user, sqlite3* db, int newfd)
{
char sql[MAX]="";
sprintf(sql, "delete from staffMessage where id=%d",user.id);
if(sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK)
{
printf("删除用户失败\n");
strcpy(sql,"删除失败");//反馈信息
}else
{
printf("删除用户成功\n");
//插入操作记录
struct tm *time = getTime();
sprintf(sql, "insert into history values (\"删除用户 ID:%d\",\"%d/%d/%d %d:%d\",1234);", user.id,time->tm_year+1900,time->tm_mon+1,time->tm_mday,time->tm_hour,time->tm_min);
if(sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK)
{
printf("添加记录失败\n");
return -1;
}
strcpy(sql,"删除成功");//反馈信息
}
//发送反馈信息
if(send(newfd, sql, sizeof(sql), 0) < 0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
//更新用户信息
int rootUpdate(Msg_t user, sqlite3* db, int newfd)
{
char sql[MAX]="";
switch (user.cmd)
{
case UPDATE_NAME:
sprintf(sql, "update staffMessage set name=\"%s\" where id=%d",user.name, user.id);
break;
case UPDATE_AGE:
sprintf(sql, "update staffMessage set age=%d where id=%d",user.age, user.id);
break;
case UPDATE_SEX:
sprintf(sql, "update staffMessage set sex=\"%c\" where id=%d",user.sex, user.id);
break;
case UPDATE_DEPARTMENT:
sprintf(sql, "update staffMessage set department=\"%s\" where id=%d",user.department, user.id);
break;
case UPDATE_PHONE:
sprintf(sql, "update staffMessage set phone=\"%s\" where id=%d",user.phone, user.id);
break;
case UPDATE_PASSWD:
sprintf(sql, "update staffMessage set passwd=\"%s\" where id=%d",user.passwd, user.id);
break;
default:
break;
}
if(sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK)
{
printf("修改用户信息失败\n");
strcpy(sql,"修改失败");//反馈信息
}else
{
printf("修改用户成功\n");
//插入操作记录
struct tm *time = getTime();
sprintf(sql, "insert into history values (\"修改用户信息ID:%d\",\"%d/%d/%d %d:%d\",1234);", user.id,time->tm_year+1900,time->tm_mon+1,time->tm_mday,time->tm_hour,time->tm_min);
if(sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK)
{
printf("添加记录失败\n");
return -1;
}
strcpy(sql,"修改成功");//反馈信息
}
//发送反馈信息
if(send(newfd, sql, sizeof(sql), 0) < 0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
//查询用户信息
int rootFind(Msg_t user, sqlite3* db, int newfd)
{
char sql[MAX]="";
char** buf;
int row;
int column;
int i;
if(user.cmd == FIND_ID)
{
sprintf(sql, "select * from staffMessage where id=%d;", user.id);
if(sqlite3_get_table(db, sql, &buf, &row, &column, NULL)!= SQLITE_OK)
{
printf("查询失败\n");
return -1;
}
//只发生对应工号的所有数据
for(i=7;i<(row+1)*column; i++)
{
if(send(newfd, buf[i], MAX, 0) < 0)
{
ERR_MSG("send");
return -1;
}
}
}else
{
strcpy(sql, "select * from staffMessage;");
if(sqlite3_get_table(db, sql, &buf, &row, &column, NULL)!= SQLITE_OK)
{
printf("查询失败\n");
return -1;
}
for(i=14;i<(row+1)*column; i++)
{
if(send(newfd, buf[i], MAX, 0) < 0)
{
ERR_MSG("send");
return -1;
}
}
}
//告诉客户端信息发送完成
strcpy(sql,"finish");
if(send(newfd, sql, sizeof(sql), 0) < 0)
{
ERR_MSG("send");
return -1;
}
struct tm *time = getTime();
sprintf(sql, "insert into history values (\"查询用户信息\",\"\t%d/%d/%d %d:%d\",1234);",time->tm_year+1900,time->tm_mon+1,time->tm_mday,time->tm_hour,time->tm_min);
if(sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK)
{
printf("添加记录失败\n");
return -1;
}
return 0;
}
//查询历史数据
int rootHistory(Msg_t user, sqlite3* db, int newfd)
{
char sql[MAX] = "select * from history;";
char** buf;
int row;
int column;
if(sqlite3_get_table(db, sql, &buf, &row, &column, NULL)!= SQLITE_OK)
{
printf("查询失败\n");
return -1;
}
int i;
for(i=0;i<(row+1)*column; i++)
{
if(send(newfd, buf[i], MAX, 0) < 0)
{
ERR_MSG("send");
return -1;
}
}
//发送反馈信息
strcpy(sql,"finish");
if(send(newfd, sql, sizeof(sql), 0) < 0)
{
ERR_MSG("send");
return -1;
}
struct tm *time = getTime();
sprintf(sql, "insert into history values (\"查询历史记录\",\"\t%d/%d/%d %d:%d\",1234);",time->tm_year+1900,time->tm_mon+1,time->tm_mday,time->tm_hour,time->tm_min);
if(sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK)
{
printf("添加记录失败\n");
return -1;
}
return 0;
}
//登录菜单
unsigned int loginMenu()
{
unsigned int chose;
while(1)
{
printf("************员工管理系统************\n");
printf("***********1.管理员模式************\n");
printf("***********2.普通用户模式**********\n");
printf("***********0.退出系统**************\n");
printf("请输入您的选项:");
scanf("%d",&chose);
if(chose>2)
{
printf("输入有误,请重新输入\n");
}else
{
return chose;
}
system("clear");//清屏
}
}
//输入账号密码
Msg_t login(Msg_t user, int cmd)
{
user.cmd = cmd;
printf("请输入工号:");
scanf("%d",&user.id);
while(getchar() != '\n');
printf("请输入密码:");
fgets(user.passwd, sizeof(user), stdin);
user.passwd[strlen(user.passwd)-1] = '\0';
return user;
}
//管理员菜单
unsigned int rootMenu()
{
unsigned int chose;
while(1)
{
printf("*************员工管理系统*************\n");
printf("*************1.添加用户***************\n");
printf("*************2.删除用户***************\n");
printf("*************3.修改信息***************\n");
printf("*************4.查看用户***************\n");
printf("*************5.历史记录***************\n");
printf("*************0.退出系统***************\n");
printf("请输入您的选项:");
scanf("%d",&chose);
getchar();
if(chose>5)
{
printf("输入有误,请重新输入\n");
}else
{
return chose;
}
system("clear");//清屏
}
}
//请求添加用户
int addUser(int sfd, Msg_t user)
{
user.cmd = ADD_USER;
printf("请输入工号:");
scanf("%d",&user.id);
while(getchar() != '\n');
printf("请输入名字:");
fgets(user.name, sizeof(user), stdin);
user.name[strlen(user.name)-1] = '\0';
printf("请输入年龄:");
scanf("%d",&user.age);
while(getchar() != '\n');
printf("请输入性别:");
scanf("%c",&user.sex);
while(getchar() != '\n');
printf("请输入部门:");
fgets(user.department, sizeof(user), stdin);
user.department[strlen(user.department)-1] = '\0';
printf("请输入号码:");
fgets(user.phone, sizeof(user), stdin);
user.phone[strlen(user.phone)-1] = '\0';
printf("请输入密码:");
fgets(user.passwd, sizeof(user), stdin);
user.passwd[strlen(user.passwd)-1] = '\0';
//发送数据包
if(send(sfd, &user, sizeof(user), 0) < 0)
{
ERR_MSG("send");
return -1;
}
//阻塞等待反馈信息
char buf[MAX];
if(recv(sfd, buf, sizeof(buf), 0) < 0)
{
return -1;
}
printf("%s\n",buf);
return 0;
}
//请求删除用户
int deleteUser(int sfd,Msg_t user)
{
user.cmd = DEL_USER;
printf("请输入要删除的工号:");
scanf("%d",&user.id);
while(getchar() != '\n');
//发送数据包
if(send(sfd, &user, sizeof(user), 0) < 0)
{
ERR_MSG("send");
return -1;
}
//阻塞等待反馈信息
char buf[MAX];
if(recv(sfd, buf, sizeof(buf), 0) < 0)
{
return -1;
}
printf("%s\n",buf);
return 0;
}
//请求更新数据
int updateUser(int sfd, Msg_t user)
{
if(user.cmd == ROOT_LOGIN)
{
printf("请输入要修改员工的工号:");
scanf("%d",&user.id);
while(getchar() != '\n');
}
unsigned int chose;
while(1)
{
do
{
printf("1:修改姓名\n2:修改年龄\n3:修改性别\n4:修改部门\n5:修改号码\n6:修改密码\n0:退出\n");
printf("请输入选项:");
scanf("%d",&chose);
getchar();
}while(chose>6);
switch(chose)
{
case 0:
return 0;
case 1:
user.cmd = UPDATE_NAME;
printf("请输入名字:");
fgets(user.name, 50, stdin);
user.name[strlen(user.name)-1] = '\0';
break;
case 2:
user.cmd = UPDATE_AGE;
printf("请输入年龄:");
scanf("%d",&user.age);
while(getchar() != '\n');
break;
case 3:
user.cmd = UPDATE_SEX;
printf("请输入性别:");
scanf("%c",&user.sex);
while(getchar() != '\n');
break;
case 4:
user.cmd = UPDATE_DEPARTMENT;
printf("请输入部门:");
fgets(user.department, sizeof(user), stdin);
user.department[strlen(user.department)-1] = '\0';
break;
case 5:
user.cmd = UPDATE_PHONE;
printf("请输入号码:");
fgets(user.phone, sizeof(user), stdin);
user.phone[strlen(user.phone)-1] = '\0';
break;
case 6:
user.cmd = UPDATE_PASSWD;
printf("请输入密码:");
fgets(user.passwd, sizeof(user), stdin);
user.passwd[strlen(user.passwd)-1] = '\0';
break;
}
//发送数据包
if(send(sfd, &user, sizeof(user), 0) < 0)
{
ERR_MSG("send");
return -1;
}
//阻塞等待反馈信息
char buf[MAX];
if(recv(sfd, buf, sizeof(buf), 0) < 0)
{
return -1;
}
printf("%s\n",buf);
printf("是否继续修改 1:是 0:否\n");
scanf("%d", &chose);
getchar();
if(!chose)
{
break;
}
}
return 0;
}
//请求查询用户信息
int findUser(int sfd, Msg_t user)
{
unsigned int chose;
if(user.cmd == ROOT_LOGIN)
{
do{
printf("1:查看所有员工信息\n2:指定工号查看\n0:退出\n请输入选项:");
scanf("%d",&chose);
getchar();
}while(chose>2);
switch (chose)
{
case 0:
break;
case 1:
user.cmd = FIND_ALL;
break;
case 2:
user.cmd = FIND_ID;
printf("请输入工号:");
scanf("%d",&user.id);
getchar();
break;
default:
break;
}
}else
{
user.cmd = FIND_ID;
}
//发送数据包
if(send(sfd, &user, sizeof(user), 0) < 0)
{
ERR_MSG("send");
return -1;
}
//接收信息
int i=0,res;
char buf[MAX];
while(1)
{
res = recv(sfd, buf, sizeof(buf), 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
if(strcmp(buf,"finish")==0)
{
break;
}
if(strlen(buf))
{
printf("%s\t",buf);
i++;
}
if(i==7)
{
i=0;
putchar(10);
}
}
}
//请求查询历史操作记录
int history(int sfd, Msg_t user)
{
user.cmd = HISTORY;
//发送数据包
if(send(sfd, &user, sizeof(user), 0) < 0)
{
ERR_MSG("send");
return -1;
}
int i=0,res;
char buf[256];
while(1)
{
res = recv(sfd, buf, sizeof(buf), 0);
if(res < 0)
{
return -1;
}
if(strcmp(buf,"finish")==0)
{
break;
}
if(strlen(buf))
{
printf("%s\t",buf);
i++;
}
if(i==3)
{
i=0;
putchar(10);
}
}
putchar(10);
}
//普通用户菜单
unsigned int generalMenu()
{
unsigned int chose;
while(1)
{
printf("***********员工管理系统************\n");
printf("*************1.查询***************\n");
printf("*************2.修改***************\n");
printf("*************0.退出***************\n");
printf("请输入您的选项:");
scanf("%d",&chose);
if(chose>2)
{
printf("输入有误,请重新输入\n");
}else
{
return chose;
}
}
}
服务器代码 server.c
#include "./common.h"
int main(int argc, char const *argv[])
{
//回收僵尸进程
if(SIG_ERR == signal(SIGCHLD, handler))
{
perror("signal");
return -1;
}
//检查外部传参是否正确
if(argc != 3)
{
printf("需外部传参 IP port\n");
return -1;
}
//打开数据库
sqlite3* db = NULL;
if(sqlite3_open("./my.db", &db) != SQLITE_OK)
{
printf("打开数据库失败\n");
return -1;
}
//创建一个表格,用于记录员工信息
char* sql = "create table if not exists staffMessage (id int primary key, name char, age int, sex char, department char, phone char, passwd char);" ;
if(sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK)
{
printf("创建表失败\n");
return -1;
}
//创建一个表,用于记录操作日志
sql = "create table if not exists history (operation_note char, time char, id int);" ;
if(sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK)
{
printf("创建表失败\n");
return -1;
}
//默认管理员账号(ID:1 密码:admin)
sql = "insert into staffMessage values (1,'root',0,'x',\"xxx\",\"xxx\",\"admin\");";
sqlite3_exec(db, sql, NULL, NULL, NULL);
//创建字节流式套接字
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
//允许端口快速复用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))<0)
{
ERR_MSG("setsockopt");
return -1;
}
//填充服务器自身地址信息
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(atoi(argv[2]));
sin.sin_addr.s_addr = inet_addr(argv[1]);
//绑定地址信息到套接字上
if(bind(sfd, (struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("bind");
return -1;
}
//设置为被动监听状态
if(listen(sfd, 128)<0)
{
ERR_MSG("listen");
return -1;
}
//接收客户端地址信息
struct sockaddr_in cin;
socklen_t cinLen = sizeof(cin);
//创建一个子进程,父进程用于接收客服端的套接字,子进程用户服务器与客户端通讯
printf("准备就绪\n");
while(1)
{
//获取用于通讯的套接字
int newfd = accept(sfd,(struct sockaddr*)&cin, &cinLen);
if(newfd<0)
{
ERR_MSG("accept");
return -1;
}
printf("[%s:%d]已连接\n",inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
pid_t pid = fork();
if(pid<0)
{
ERR_MSG("fork");
return -1;
}else if(0 == pid)//子进程
{
char buf[MAX];
ssize_t res = 0;
close(sfd);//关闭父进程中的套接字
//循环接收
Msg_t user;
while(1)
{
bzero(buf, sizeof(buf));
res = recv(newfd, buf, sizeof(buf), 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
printf("[%s:%d]退出连接\n",inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
close(newfd);
exit(0);
}
//转换消息包类型
user = *(Msg_t*)buf;
//解析数据包
switch (user.cmd)
{
case ROOT_LOGIN:
case USER_LOGIN:
isLogin(user, db, newfd);
break;
case ADD_USER:
rootAddUser(user, db, newfd);
break;
case DEL_USER:
rootDelUser(user, db, newfd);
break;
case UPDATE_NAME:
case UPDATE_AGE:
case UPDATE_SEX:
case UPDATE_DEPARTMENT:
case UPDATE_PHONE:
case UPDATE_PASSWD:
rootUpdate(user, db, newfd);
break;
case FIND_ALL:
case FIND_ID:
rootFind(user, db, newfd);
break;
case HISTORY:
rootHistory(user, db, newfd);
break;
default:
break;
}
}
}
close(newfd);//父进程关闭子进程中用于通信的套接字
}
//接收信息
//发送信息
return 0;
}
客户端代码 client.c
#include "./common.h"
int main(int argc, char const *argv[])
{
//检查外部传参是否正确
if(argc != 3)
{
printf("需外部传参 IP port\n");
return -1;
}
//创建字节流式套接字
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
//允许端口快速复用
int reuse = 1;
if(0 > setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)))
{
ERR_MSG("setsockopt");
return -1;
}
//填充服务器地址信息
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(atoi(argv[2]));
sin.sin_addr.s_addr = inet_addr(argv[1]);
//连接服务器
if(connect(sfd,(struct sockaddr*)&sin, sizeof(sin))<0)
{
ERR_MSG("connect");
return -1;
}
char buf[MAX];
ssize_t res;
Msg_t user;
unsigned int chose;
while(1)
{
memset(&user, 0, sizeof(user));//清空信息包,避免干扰
bzero(buf,sizeof(buf));//清空字符数组,避免干扰
chose = loginMenu();
switch(chose)
{
case 1:
user = login(user, ROOT_LOGIN);
break;
case 2:
user = login(user, USER_LOGIN);
break;
case 0:
close(sfd);
exit(0);
default:
close(sfd);
exit(0);
}
//发送数据包
if(send(sfd, &user, sizeof(user), 0) < 0)
{
ERR_MSG("send");
return -1;
}
//接收反馈信息
res = recv(sfd, buf, sizeof(buf), 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
printf("%s\n",buf);
if(strcmp(buf, "success")==0)//登录成功
{
if(user.cmd==ROOT_LOGIN)//管理员登录成功
{
while(1)
{
chose = rootMenu();
switch(chose)
{
case 0:
close(sfd);
exit(0);
case 1:
addUser(sfd, user);
break;
case 2:
deleteUser(sfd, user);
break;
case 3:
updateUser(sfd, user);
break;
case 4:
findUser(sfd, user);
break;
case 5:
history(sfd, user);
break;
default:
break;
}
}
}else//普通用户登录成功
{
while(1)
{
chose = generalMenu(sfd,user);
switch(chose)
{
case 0:
close(sfd);
exit(0);
break;
case 1:
findUser(sfd, user);
break;
case 2:
updateUser(sfd, user);
break;
default:
break;
}
}
}
}
}
close(sfd);
//接收信息
//发送信息
return 0;
}
测试视频:
员工管理系统测试视频