1.服务器
1.1服务器函数入口
#include "server.h"
int main(int argc, char const *argv[])
{
char buf[128] = {0};
char buf_ID[256] = {0};
// 接收报错信息判断
sqlite3 *db;
// 创建员工信息的表格,存在则打开
db = Sqlite_Create();
if (db == NULL)
{
printf("sqlite_create=NULL\n");
return 0;
}
// 服务器 套接字->端口重启->绑定->监听
int sock_fd = sock_listen();
if (!sock_fd)
{
printf("流程出现故障%d\n", __LINE__);
return 0;
}
// 创建红黑树根节点
// 创建一个epoll句柄/红黑树根节点
epfd = epoll_create(10);
if (epfd < 0)
{
printf("epoll_create on_success _%d_", __LINE__);
return 0;
}
// 添加监听连接事件到红黑树节点中
add_epoll(epfd, sock_fd);
// 到此,以上流程全部正确走完
// 客户端信息结构体的大小
socklen_t addrlen = sizeof(my_cin);
/*********与客户端互动区域_begin*********/
// 存储连接的所有客户端描述符
// str_newfd *arr_newfd;
// arr_newfd->len
// 新连接的客户端返回的描述符
int newfd = -1;
// 最下的客户端描述符
int midfd = -1;
ser_cli my_ser_cli;
str_staff my_str_staff;
while (1)
{
// ret返回就绪事件的个数,并将就绪的事件放入到
// events这个结构体中,参3表示最多放入10个事件,
// 参4的-1表示不关心是否超时
int ret = epoll_wait(epfd, events, 10, -1);
if (ret < 0 || ret > 10)
{
printf("epoll_wait on_success:%d\n", __LINE__);
return 0;
}
/****走到这里,表示有事件准备就绪****/
for (int i = 0; i < ret; i++)
{
// 客户端连接事件发生
if (events[i].data.fd == sock_fd)
{
newfd = accept(sock_fd, (struct sockaddr *)&my_cin, &addrlen);
if (newfd < 0)
{
ERR_MSG("accept");
return -1;
}
if (add_epoll(epfd, newfd) < 0)
{
printf("add_epoll errno%d\n", __LINE__);
return 0;
}
printf("newfd=%d连接成功\n", newfd);
// 判断新描述符的大小,放入到顺序表中
// pai_arr_newfd(arr_newfd,newfd);
}
else
{
ser_cli my_ser_cli;
str_staff my_str_staff;
// 创建一个线程
pthread_t tid;
my_ser_cli.fd = events[i].data.fd;
// 接收客户端数据,进入账号密码的判断,是root还是普通
// 接收服务器的信息
int ser_fd=my_ser_cli.fd;
if (recv(my_ser_cli.fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
printf("接收失败%d\n", __LINE__);
return 0;
}
if (my_ser_cli.CLI_SELECT == 3) // 用户选择退出
{
quit(my_ser_cli);
}
// 往下走说明是用户和root登陆
// 当事件发生以后移除文件描述符
my_ser_cli.events_i = i;
my_ser_cli.db = db;
my_ser_cli.fd = ser_fd;
if (pthread_create(&tid, NULL, callBack, (void *)&my_ser_cli) != 0)
{
printf("%ld线程创建失败%d\n", tid, __LINE__);
return 0;
}
remove_fd(&my_ser_cli);//账号下线,清楚其存在
}
}
}
/*********与客户端互动区域_end*********/
// 释放资源
return 0;
}
1.2服务器运行代码
#include "server.h"
int flag = 0;
int fd_flag = 0;
// 创建数据库并打开数据表
sqlite3 *Sqlite_Create(void)
{
/*表格信息: 1.主键(int id),用于判断该账号是用户还是管理员
2.员工姓名(char name)
2.员工工号(int jobnumner)
3.员工年龄(int age)
4.当前薪资(float wage)
5.岗位名称(char post)
6.手机号(int phone )
7.入职时间 (char time)精确到日
8.是否在线 (state int) 1表示在线 0不在线*/
// 存储SQL的报错信息
char *errmsg = NULL;
// 创建并打开数据库
sqlite3 *db = NULL;
if (sqlite3_open("./staff.db", &db) != SQLITE_OK)
{
printf("sqlite3_open errno %d\n", __LINE__);
return NULL;
}
debuf_db = db;
// 组装SQL语句创建数据表
char sql[528] = "create table if not exists staff(id int,name char,jobnumber int,age int,wage float,post char,phone int,time char,state int,pass_w int);";
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec: %s\n", __LINE__, errmsg);
return NULL;
}
return db;
}
// 服务器 套接字->端口重启->绑定->监听
int sock_listen(void)
{
// 一.创建套接字1.AF_INET默认为ip(7)协议 2.SOCK_STREAM默认为TCP
// 3.0表示使用type对应的默认协议
int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0)
{
ERR_MSG("socket");
goto OUT1;
}
// 端口快速启用
int resue = 1;
if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &resue, sizeof(resue)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
// 填充服务器信息结构体
my_ser.sin_family = AF_INET; // IPv4协议指向填充
my_ser.sin_port = htons(PORT); // 将端口转换成网络字节
my_ser.sin_addr.s_addr = inet_addr(IP); // IP地址转换成网络字节序
// 绑定服务器的IP和端口
if (bind(sock_fd, (struct sockaddr *)&my_ser, sizeof(my_ser)) < 0)
{
ERR_MSG("bind");
goto OUT2;
}
// 将套接字设置为被动监听,最多监听128个
if (listen(sock_fd, 128) < 0)
{
ERR_MSG("listen");
goto OUT2;
}
return sock_fd;
OUT2:
close(sock_fd);
OUT1:
return 0;
}
// 红黑树监听事件信息的添加
int add_epoll(int epfd, int fd)
{
// 将套接字的信息存入到event结构体中,为事件放入红黑树中做准备
event.events = EPOLLIN; // 关注可读事件,套接字有数据可读时触发
event.data.fd = fd;
// 将event存放到套接字信息放入到红黑树中
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event) < 0)
{
printf("epoll_ctl on_success _%d_", __LINE__);
return 0;
}
return 1;
}
int remove_epoll(int epfd, int fd)
{
// 将套接字的信息存入到event结构体中,为事件放入红黑树中做准备
event.data.fd = fd;
// 将event存放到套接字信息放入到红黑树中
if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0)
{
ERR_MSG("epoll_ctl");
return 0;
}
return 1;
}
// 客户端的描述符在顺序表中添加后的排序
// void paixu_arr_newfd(str_newfd *arr_newfd,int newfd)
// {
// int i,j,count;
// arr_newfd->arr[arr_newfd->len].fd=newfd;
// arr_newfd->len++;
// for(i=1;i<=arr_newfd->len;i++)
// {
// count=0;
// for(j=0;j<arr_newfd.)
// }
// }
// 资源的释放函数
// 创建一个线程处理客户端交互
void *callBack(void *arg)
{
// 组装SQL语句
char sql[256] = "";
char **pres = NULL;
int row, column;
char *errmsg;
int jobnumber, pass_w;
ser_cli *my_ser_cli = (ser_cli *)arg;
char debug[128] = "kkk";
ser_cli my_ser_cli_C = *my_ser_cli;
// 判断账号是否存在
sprintf(sql, "select * from staff where jobnumber=%d;", my_ser_cli->staff_information.jobnumber);
// printf("%s%d\n", debug,__LINE__);
if (sqlite3_get_table(my_ser_cli->db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
printf("get_table_jobnumber error%s %d\n", errmsg, __LINE__);
return 0;
}
else
{
if (row == 0)
{
// 账号不存在
my_ser_cli->cli_n_p = 1; // 该位写1账号不存在
my_ser_cli_C = *my_ser_cli;
send(my_ser_cli->fd, &my_ser_cli_C, sizeof(my_ser_cli_C), 0);
return 0;
}
// 判断密码是否与账号匹配
sprintf(sql, "select * from staff where jobnumber=%d and pass_w=%d;", my_ser_cli->staff_information.jobnumber, my_ser_cli->staff_information.pass_w);
if (sqlite3_get_table(my_ser_cli->db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
printf("get_table_pass_w error %d\n", __LINE__);
return 0;
}
else
{
if (row == 0)
{
// 账号错误
my_ser_cli->cli_n_p = 2; // 账号匹配密码不正确s
my_ser_cli_C = *my_ser_cli;
printf("密码不正确\n");
send(my_ser_cli->fd, &my_ser_cli_C, sizeof(my_ser_cli_C), 0);
return 0;
}
else // 判断是root还是用户
{
// 判断用户还是root
sprintf(sql, "select * from staff where id=%d;", my_ser_cli->staff_information.key);
if (sqlite3_get_table(my_ser_cli->db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
printf("get_table_pass_w error %d\n", __LINE__);
return 0;
}
else
{
if (row == 0 && my_ser_cli->CLI_SELECT == 1) // 管理员进错到用户
{
my_ser_cli->cli_n_p = 3; // 管理员进错到用户
my_ser_cli_C = *my_ser_cli;
send(my_ser_cli->fd, &my_ser_cli_C, sizeof(my_ser_cli_C), 0);
return 0;
}
else if (row == 0 && my_ser_cli->CLI_SELECT == 2) // 用户不能访问管理
{
my_ser_cli->cli_n_p = 4; // 用户不能访问管理
my_ser_cli_C = *my_ser_cli;
send(my_ser_cli->fd, &my_ser_cli_C, sizeof(my_ser_cli_C), 0);
return 0;
}
if (remove_epoll(epfd, my_ser_cli->fd) == 0)
{
printf("remove_epoll errno%d\n", __LINE__);
my_ser_cli->cli_n_p = 1; // 用户不能访问管理
my_ser_cli_C = *my_ser_cli;
send(my_ser_cli->fd, &my_ser_cli_C, sizeof(my_ser_cli_C), 0);
return 0;
}
// 走到这里,表示均匹配成功
my_ser_cli->cli_n_p = 5;
// 将员工号存到数组里,用于历史记录查询
add_jobnumber_A(my_ser_cli);
my_ser_cli_C = *my_ser_cli;
if(add_fd(my_ser_cli)==0)//判断账号是否重复登陆
{
//表示账号属于重复登陆
my_ser_cli_C.flag=0;//告诉客户端重复登陆
send(my_ser_cli->fd, &my_ser_cli_C, sizeof(my_ser_cli_C), 0);
return 0;
}
my_ser_cli_C.flag=1;//告诉客户端没有重复登陆
printf("%d %d\n",my_ser_cli_C.flag,__LINE__);
send(my_ser_cli->fd, &my_ser_cli_C, sizeof(my_ser_cli_C), 0);//走到这里,表示客户端连接成功
while (1)
{
switch (my_ser_cli->CLI_SELECT)
{
case 1: // 控制管理员界面
if (root_ui(my_ser_cli) == 0)
{
pthread_detach(tid);
return 0;
}
break;
case 2: // 员工管理员界面
if (user_ui(my_ser_cli) == 0)
{
return 0;
}
break;
default:
break;
}
}
}
}
}
return 0;
}
return 0;
}
// 员工历史记录添加
int add_jobnumber_A(ser_cli *my_ser_cli_H)
{
// 重新保存
ser_cli my_ser_cli = *my_ser_cli_H;
jobnumber_A[0].flag = flag++; // 存放下一次新的工号存储位置
printf("flag=%d\n", flag);
// 判断该账号是否以及存在于数组
for (int i = 0; i < 10; i++)
{
if (jobnumber_A[i].staff_information.jobnumber == my_ser_cli.staff_information.jobnumber) // 已经在数组中
{
return 0; // 不做添加
}
}
// 走到这里表示该账号不存在数组中,添加
jobnumber_A[jobnumber_A[0].flag].staff_information.jobnumber = my_ser_cli.staff_information.jobnumber;
}
int root_ui(ser_cli *my_ser_cli)
{
char sql[528] = "";
ser_cli my_ser_cli_ui;
ser_cli my_ser_cli_ui_1; // 除case1以外使用的
str_staff my_str_staff;
// my_ser_cli_ui.staff_information = my_str_staff;
my_ser_cli_ui.fd = my_ser_cli->fd;
printf("\n管理%d进入root界面%d\n", my_ser_cli->staff_information.jobnumber, __LINE__);
char **pres = NULL;
int row, column;
char *errmsg;
int jobnumber, pass_w;
// 接收管理员操作指令码
while (1)
{
my_ser_cli_ui.staff_information.jobnumber = 0;
if (recv(my_ser_cli->fd, &my_ser_cli_ui, sizeof(my_ser_cli_ui), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
my_ser_cli_ui_1 = my_ser_cli_ui; // 备份,防止2345的操作影响到1
my_ser_cli_ui_1.db = my_ser_cli->db;
my_ser_cli_ui_1.fd = my_ser_cli->fd;
switch (my_ser_cli_ui.CLI_SELECT_H)
{
case 1: // 添加员工信息
// 判断账号是否存在
sprintf(sql, "select * from staff where jobnumber=%d;", my_ser_cli_ui.staff_information.jobnumber);
// printf("%s%d\n", debug,__LINE__);
if (sqlite3_get_table(my_ser_cli->db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
printf("get_table_jobnumber error%s %d\n", errmsg, __LINE__);
return 0;
}
if (row != 0) // 表示工号已经存在
{
my_ser_cli_ui.CLI_SELECT = 1;
if (send(my_ser_cli->fd, &my_ser_cli_ui, sizeof(my_ser_cli_ui), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
return 0;
}
if (my_ser_cli->staff_information.jobnumber)
{
sprintf(sql, "insert into staff values (%d, '%s', %d, %d, %f, '%s', %d, '%s', %d, %d);", my_ser_cli_ui.staff_information.key,
my_ser_cli_ui.staff_information.name, my_ser_cli_ui.staff_information.jobnumber, my_ser_cli_ui.staff_information.age, my_ser_cli_ui.staff_information.wage,
my_ser_cli_ui.staff_information.post, my_ser_cli_ui.staff_information.phone, my_ser_cli_ui.staff_information.time, my_ser_cli_ui.staff_information.state,
my_ser_cli_ui.staff_information.pass_w);
if (sqlite3_exec(my_ser_cli->db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec: %s\n", __LINE__, errmsg);
return 0;
}
// 告诉客户端注册完毕
if (send(my_ser_cli->fd, &my_ser_cli_ui, sizeof(my_ser_cli_ui), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
}
break;
case 2:
root_xiugai_ser(&my_ser_cli_ui_1); // 修改员工信息
break;
case 3:
root_chaxun_user(&my_ser_cli_ui_1); // 查询员工信息
break;
case 4:
root_lishi_user(&my_ser_cli_ui_1); // 发送历史查询记录
break;
case 5:
printf("管理系统退出成功\n");
return 0;
break;
default:
printf("输入错误,请重新输入\n");
return 0;
break;
}
}
}
// 服务器向root发送历史记录表
int root_lishi_user(ser_cli *my_ser_cli_H)
{
printf("root调用历史信息表\n");
char **pres = NULL;
int row, column;
char *errmsg = NULL;
int jobnumber, pass_w;
char sql[528] = "";
int index = 10;
printf("flag_A=%d\n", flag);
for (int i = 0; i < flag; i++)
{
// 将存在的所有放到数组里面
memset(sql, '0', sizeof(sql));
sprintf(sql, "select * from staff where jobnumber=%d;", jobnumber_A[i].staff_information.jobnumber);
if (sqlite3_get_table(my_ser_cli_H->db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
printf("get_table_jobnumber error%s %d\n", errmsg, __LINE__);
return 0;
}
if (row == 0) // 表示没有找到,向服务器发送信息
{
printf("出现错误 工号不存在%d\n", __LINE__);
}
else
{
// 走到这里表示工号存在,将员工信息填充发送带客户端
// 发送
jobnumber_A[i].staff_information.key = atoi(pres[index++]);
strcpy(jobnumber_A[i].staff_information.name, pres[index++]);
jobnumber_A[i].staff_information.jobnumber = atoi(pres[index++]);
jobnumber_A[i].staff_information.age = atoi(pres[index++]);
jobnumber_A[i].staff_information.wage = atof(pres[index++]);
strcpy(jobnumber_A[i].staff_information.post, pres[index++]);
jobnumber_A[i].staff_information.phone = atoi(pres[index++]);
strcpy(jobnumber_A[i].staff_information.time, pres[index++]);
jobnumber_A[i].staff_information.state = atoi(pres[index++]);
jobnumber_A[i].staff_information.pass_w = atoi(pres[index++]);
}
if (send(my_ser_cli_H->fd, jobnumber_A, sizeof(*(jobnumber_A)), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
printf("历史记录表成功发送\n");
}
}
int root_chaxun_user(ser_cli *my_ser_cli_H)
{
if (my_ser_cli_H->staff_information.key == 1)
printf("root进入查询界面%d\n", __LINE__);
else
printf("用户进入查询界面%d\n", __LINE__);
ser_cli my_ser_cli = *my_ser_cli_H;
char **pres = NULL;
int row, column;
char *errmsg = NULL;
int jobnumber, pass_w;
char sql[528] = "";
// printf("SELETC=%d line:%d\n", my_ser_cli.CLI_SELECT, __LINE__);
switch (my_ser_cli.CLI_SELECT)
{
case 1:
// 进入按员工号查找
sprintf(sql, "select * from staff where jobnumber=%d;", my_ser_cli.staff_information.jobnumber);
if (sqlite3_get_table(my_ser_cli.db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
printf("get_table_jobnumber error%s %d\n", errmsg, __LINE__);
return 0;
}
if (row == 0) // 表示没有找到,向服务器发送信息
{
printf("debuf%d\n", __LINE__);
my_ser_cli.CLI_SELECT = 2; // 0是修改,2是不存在
if (send(my_ser_cli_H->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
}
else
{
// 走到这里表示工号存在,将员工信息填充发送带客户端
// 发送
int index = 10;
my_ser_cli.staff_information.key = atoi(pres[index++]);
strcpy(my_ser_cli.staff_information.name, pres[index++]);
my_ser_cli.staff_information.jobnumber = atoi(pres[index++]);
my_ser_cli.staff_information.age = atoi(pres[index++]);
my_ser_cli.staff_information.wage = atof(pres[index++]);
strcpy(my_ser_cli.staff_information.post, pres[index++]);
my_ser_cli.staff_information.phone = atoi(pres[index++]);
strcpy(my_ser_cli.staff_information.time, pres[index++]);
my_ser_cli.staff_information.state = atoi(pres[index++]);
my_ser_cli.staff_information.pass_w = atoi(pres[index++]);
my_ser_cli.CLI_SELECT = 0; // 0是查询成功
if (send(my_ser_cli_H->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
}
break;
case 2:
printf("进入按手机号查询");
sprintf(sql, "select * from staff where phone=%d;", my_ser_cli.staff_information.phone);
if (sqlite3_get_table(my_ser_cli.db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
printf("get_table_jobnumber error%s %d\n", errmsg, __LINE__);
return 0;
}
if (row == 0) // 表示没有找到,向服务器发送信息
{
my_ser_cli.CLI_SELECT = 2; // 0是修改,2是不存在
if (send(my_ser_cli_H->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
}
else
{
// 进入这表示手机存在,填充信息
int index = 10;
my_ser_cli.staff_information.key = atoi(pres[index++]);
strcpy(my_ser_cli.staff_information.name, pres[index++]);
my_ser_cli.staff_information.jobnumber = atoi(pres[index++]);
my_ser_cli.staff_information.age = atoi(pres[index++]);
my_ser_cli.staff_information.wage = atof(pres[index++]);
strcpy(my_ser_cli.staff_information.post, pres[index++]);
my_ser_cli.staff_information.phone = atoi(pres[index++]);
strcpy(my_ser_cli.staff_information.time, pres[index++]);
my_ser_cli.staff_information.state = atoi(pres[index++]);
my_ser_cli.staff_information.pass_w = atoi(pres[index++]);
my_ser_cli.CLI_SELECT = 0; // 0是查询成功
if (send(my_ser_cli_H->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
}
break;
default:
printf("未定义指令码%d %d\n", my_ser_cli.CLI_SELECT, __LINE__);
return 0;
break;
}
}
int root_xiugai_ser(ser_cli *my_ser_cli_H)
{
printf("进入修改界面%d\n", __LINE__);
ser_cli my_ser_cli = *my_ser_cli_H;
char **pres = NULL;
int row, column;
char *errmsg = NULL;
int jobnumber, pass_w;
char sql[528] = "";
char buf[128] = ""; // 辨别是员工号还是手机号
int key = -1; // 判断是否修改成功,跳出Switch时,值不为0,则修改成功
// 判断是根据<1>员工号还是<2>手机号码查找
switch (my_ser_cli.CLI_SELECT)
{
case 1:
sprintf(sql, "select * from staff where jobnumber=%d;", my_ser_cli.staff_information.jobnumber);
if (sqlite3_get_table(my_ser_cli.db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
printf("get_table_jobnumber error%s %d\n", errmsg, __LINE__);
return 0;
}
if (row == 0) // 表示没有找到,向服务器发送信息
{
printf("debuf%d\n", __LINE__);
my_ser_cli.CLI_SELECT = 2; // 0是修改,2是不存在
if (send(my_ser_cli_H->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
}
else // 走到这里,表示根据员工号找到对应的员工信息
{
key = 1;
// 根据flag判断修改什么
switch (my_ser_cli.flag)
{
case 1:
sprintf(sql, "update staff set name='%s' where jobnumber=%d;", my_ser_cli.staff_information.name, my_ser_cli.staff_information.jobnumber);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
break;
case 2:
sprintf(sql, "update staff set age=%d where jobnumber=%d;", my_ser_cli.staff_information.age, my_ser_cli.staff_information.jobnumber);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
break;
case 3:
sprintf(sql, "update staff set wage=%f where jobnumber=%d;", my_ser_cli.staff_information.wage, my_ser_cli.staff_information.jobnumber);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
break;
case 4:
sprintf(sql, "update staff set post='%s' where jobnumber=%d;", my_ser_cli.staff_information.post, my_ser_cli.staff_information.jobnumber);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
break;
case 5:
printf("update staff set phone=%d where jobnumber=%d;", my_ser_cli.staff_information.phone, my_ser_cli.staff_information.jobnumber);
sprintf(sql, "update staff set phone=%d where jobnumber=%d;", my_ser_cli.staff_information.phone, my_ser_cli.staff_information.jobnumber);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
break;
case 6:
sprintf(sql, "update staff set time='%s' where jobnumber=%d;", my_ser_cli.staff_information.time, my_ser_cli.staff_information.jobnumber);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
break;
case 7:
printf("1111111\n");
printf("update staff set pass_w=%d where jobnumber=%d\n;", my_ser_cli.staff_information.pass_w, my_ser_cli.staff_information.jobnumber);
sprintf(sql, "update staff set pass_w=%d where jobnumber=%d;", my_ser_cli.staff_information.pass_w, my_ser_cli.staff_information.jobnumber);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
key = 0;
printf("debuf%d\n", __LINE__);
}
break;
}
if (key) // 如果为假,表示失败,发送失败给客户端
{
my_ser_cli.CLI_SELECT = 0; // 0是修改,其他是失败
if (send(my_ser_cli_H->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
return 1;
}
}
break;
case 2:
// 因为1个变量不能存放判断的手机号和要修改的手机号,因此将判断的手机放到key变量中
sprintf(sql, "select * from staff where phone=%d;", my_ser_cli.staff_information.key);
if (sqlite3_get_table(my_ser_cli.db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
printf("get_table_jobnumber error%s %d\n", errmsg, __LINE__);
return 0;
}
if (row == 0) // 表示没有找到,向服务器发送信息
{
my_ser_cli.CLI_SELECT = 2; // 0是修改,2是不存在
if (send(my_ser_cli_H->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
}
else // 走到这里,表示根据员工号找到对应的员工信息
{
key = 1;
// 根据flag判断修改什么
switch (my_ser_cli.flag)
{
case 1:
sprintf(sql, "update staff set name='%s' where id=%d;", my_ser_cli.staff_information.name, my_ser_cli.staff_information.key);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
key = 0;
printf("debuf%d\n", __LINE__);
}
break;
case 2:
sprintf(sql, "update staff set age=%d where phone=%d;", my_ser_cli.staff_information.age, my_ser_cli.staff_information.key);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
break;
case 3:
sprintf(sql, "update staff set wage=%f where phone=%d;", my_ser_cli.staff_information.wage, my_ser_cli.staff_information.key);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
break;
case 4:
sprintf(sql, "update staff set post='%s' where phone=%d;", my_ser_cli.staff_information.post, my_ser_cli.staff_information.key);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
printf("手机号查找成功 %d\n", __LINE__);
break;
case 5:
sprintf(sql, "update staff set phone=%d where phone=%d;", my_ser_cli.staff_information.phone, my_ser_cli.staff_information.key);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
break;
case 6:
sprintf(sql, "update staff set time='%s' where phone=%d;", my_ser_cli.staff_information.time, my_ser_cli.staff_information.key);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
break;
case 7:
sprintf(sql, "update staff set pass_w=%d where phone=%d;", my_ser_cli.staff_information.pass_w, my_ser_cli.staff_information.key);
if (sqlite3_exec(my_ser_cli.db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("debuf%d\n", __LINE__);
key = 0;
}
break;
}
if (key) // 如果为假,表示失败,发送失败给客户端
{
my_ser_cli.CLI_SELECT = 0; // 0是修改成功 1是修改失败
if (send(my_ser_cli_H->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
printf("root修改信息成功 %d\n", __LINE__);
return 1;
}
break;
}
default:
printf("未定义指令码%d %d\n", my_ser_cli.CLI_SELECT, __LINE__);
return 0;
break;
}
return 1;
}
int user_ui(ser_cli *my_ser_cli)
{
char sql[528] = "";
ser_cli my_ser_cli_ui;
ser_cli my_ser_cli_ui_1; // 除case1以外使用的
my_ser_cli_ui_1.fd = my_ser_cli->fd;
str_staff my_str_staff;
// my_ser_cli_ui.staff_information = my_str_staff;
my_ser_cli_ui.fd = my_ser_cli->fd;
printf("用户%d进入用户界面\n", my_ser_cli->staff_information.jobnumber);
char **pres = NULL;
int row, column;
char *errmsg;
int jobnumber, pass_w;
// 接收管理员操作指令码
while (1)
{
my_ser_cli_ui.staff_information.jobnumber = 0;
if (recv(my_ser_cli->fd, &my_ser_cli_ui, sizeof(my_ser_cli_ui), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
my_ser_cli_ui_1 = my_ser_cli_ui; // 备份,防止2345的操作影响到1
my_ser_cli_ui_1.db = my_ser_cli->db;
my_ser_cli_ui_1.fd = my_ser_cli->fd;
switch (my_ser_cli_ui.CLI_SELECT_H)
{
case 1: // 查询个人信息
root_chaxun_user(&my_ser_cli_ui_1);
break;
case 2: // 修改个人信息
root_xiugai_ser(&my_ser_cli_ui_1);
break;
case 3: // 退出管理系统
return 0;
break;
default:
printf("输入错误,请重新输入\n");
return 0;
break;
}
}
}
int quit(ser_cli my_ser_cli)
{
printf("客户端%d退出\n", my_ser_cli.fd);
remove_epoll(epfd, my_ser_cli.fd);
close(my_ser_cli.fd);
return 0;
}
int add_fd(ser_cli *my_ser_cli_H)
{
ser_cli my_ser_cli = *my_ser_cli_H;
// 用户登录后添加账号信息到数组中,判断是否在线
for (int i = 0; i < 10; i++)
{
if (my_ser_cli.staff_information.jobnumber == fd_A[i]) // 表示账号在线,不能重复登陆
{
printf("账号%d重复登陆 line:%d\n", my_ser_cli.staff_information.jobnumber, __LINE__);
return 0;
}
}
if (flag == 10) // 重置
flag = 0;
fd_A[flag++] = my_ser_cli.staff_information.jobnumber;
return 1;
}
int remove_fd(ser_cli *my_ser_cli_H)
{
ser_cli my_ser_cli = *my_ser_cli_H;
for (int i = 0; i < 10; i++)
{
if (my_ser_cli.staff_information.jobnumber == fd_A[i]) // 找到下线账号
{
fd_A[i] = 0; // 将账号信息删除
flag--;
printf("账号%d下线 line:%d\n", my_ser_cli.staff_information.jobnumber, __LINE__);
return 0;
}
}
}
1.3服务器头文件
#ifndef __CLIENT_H__
#define __CLIENT_H__
/******头文件区域*******/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/epoll.h>
#include <sqlite3.h>
#include <pthread.h>
/******引用区域*******/
// 创建数据库并打开数据表
sqlite3 * Sqlite_Create(void);
// 服务器 套接字->端口重启->绑定->监听
int sock_listen(void);
// 红黑树监听事件信息的添加
int add_epoll(int epfd, int fd);
int remove_epoll(int epfd,int fd);
//添加线程管理交互界面
void *callBack(void *arg);
#define DEBUG_LINE printf("Debug line:%d\n",__LINE__)
// 错误码
#define ERR_MSG(msg) \
do \
{ \
fprintf(stderr, "line:%d ", __LINE__); \
perror(msg); \
} while (0)
#define PORT 6666 // 服务器端口
#define IP "192.168.250.100" // 服务器IP地址
#define MAX 10 //顺序表最大容量
// 信息结构体,因为使用IPv4,因此使用sockaddr_in填充bind的第二个参数
struct sockaddr_in my_ser; // 服务器信息结构体
struct sockaddr_in my_cin; // 保存客户端信息结构体
// 员工信息结构体
typedef struct staff
{
int key; // 判断是用户还是管理员 1是管理 2是用户
char name[128]; // 员工姓名
int jobnumber; // 员工工号
int age; // 员工年龄
float wage; // 当前的薪资
char post[128]; // 岗位名称
int phone; // 手机号
char time[128]; // 精确到日,入职时间
int state; // 是否在线 1表示在线
int pass_w; // 密码
} str_staff;
// 服务器与客户端通信的结构体
typedef struct info
{
int fd;//客户端的描述符
int CLI_SELECT; // 登陆时选择的操作 1管理员登陆,2是用户登陆 3是退出
int CLI_SELECT_H; //登陆后选择的操作 1.添加员工信息 2.修改员工记录 3.查询员工记 4.查询历史 5,退出管理
int events_i; //保存红黑树数组的下标
int cli_n_p; //高账号密码权力的匹配程度,1表示账号不存在2表示密码不正确3表示不是特权4表示不是用户5均成功
int flag;//进入2级界面选项后,传递的自定义标志位
sqlite3 *db;
str_staff staff_information; // 员工信息结构体
} ser_cli;
//客户端发送信息
int ser_cli_tongxing(ser_cli * my_str_staff,int sock_fd);
int root_ui(ser_cli *my_str_staff);
int user_ui(ser_cli *my_ser_staff);
//添加员工信息
ser_cli *add_root_and_user(ser_cli *my_ser_cli_ui);
//修改员工信息
int root_xiugai_ser(ser_cli *my_ser_cli_ui_1);
//root查询到员工信息
int root_chaxun_user(ser_cli *my_str_staff);
//添加员工信息到数组中
int add_jobnumber_A(ser_cli *my_ser_cli_H);
//root查询历史信息
int root_lishi_user(ser_cli *my_ser_cli_H);
//判断账号是否重复登陆
int add_fd(ser_cli *my_ser_cli_H);
int remove_fd(ser_cli *my_ser_cli_H);
//退出函数
int quit(ser_cli my_ser_cli);
typedef struct newfd
{
int fd;
}my_fd;
typedef struct fd_1
{
my_fd arr[MAX];
int len;
}str_newfd;
// 保存就绪事件的信息,用于移植到红黑树中
struct epoll_event event;
// 存放就绪事件描述符的数组
sqlite3 * debuf_db;
struct epoll_event events[10];
pthread_t tid;
int fd_A[10];
ser_cli jobnumber_A[10];
int epfd ;//红黑树根节点
#endif
2.客户端代码
2.1客户端函数入口
#include "client.h"
int main(int argc, char const *argv[])
{
// 创建套接字
int cfd = socket(AF_INET, SOCK_STREAM, 0);
if (cfd < 0)
{
ERR_MSG("socket");
goto OUT1;
}
// 连接服务器
// 1.填充服务器的信息
my_ser.sin_family = AF_INET;
my_ser.sin_port = htons(PORT);
my_ser.sin_addr.s_addr = inet_addr(IP);
// 连接
if (connect(cfd, (struct sockaddr *)&my_ser, sizeof(my_ser)) < 0)
{
ERR_MSG("connet");
goto OUT2;
}
printf("connect server success cfd=%d %d\n",cfd,__LINE__);
// 用户的选择
int key = -1;
ser_cli my_ser_cli; //通信结构体
str_staff my_str_staff; //员工信息
while (1)
{
printf("<*************************> 1\n");
printf("<********1.管理员登陆******> 1\n");
printf("<********2.用户登陆*******> 1\n");
printf("<********3.退出***********> 1\n");
printf("<************************> 1\n");
printf("\n请选择你要进行的操作:");
scanf("%d", &key);
switch (key)
{
case 1:
// 改变对应的结构体信息
my_ser_cli.CLI_SELECT = 1;
my_ser_cli.staff_information = my_str_staff;
my_ser_cli.fd=cfd;
my_ser_cli.staff_information.key=1;
if(ser_cli_tongxing(&my_ser_cli,cfd)==1)
{
//返回值为1表示管理员验证成功
//进入管理员控制界面
my_ser_cli.fd=cfd;
root_ui(&my_ser_cli);
}
break;
case 2:
// 改变对应的结构体信息
my_ser_cli.CLI_SELECT = 2;
my_ser_cli.staff_information = my_str_staff;
my_ser_cli.staff_information.key=2;
my_ser_cli.fd=cfd;
if(ser_cli_tongxing(&my_ser_cli,cfd)==1)
{
//表示用户登陆成功,进入用户控制界面
user_ui(&my_ser_cli);
}
break;
case 3:
// 改变对应的结构体信息
my_ser_cli.CLI_SELECT = 3;
if (send(cfd,&my_ser_cli, sizeof(my_str_staff), 0) < 0)
{
ERR_MSG("send");
}
close(cfd);
printf("退出成功\n");
exit(1);
break;
default:
printf("输入错误,请重新输入:\n");
break;
}
}
// 关闭套接字
close(cfd);
return 0;
OUT2:
close(cfd);
OUT1:
return cfd;
return 0;
}
2.2客户端执行代码
#include "client.h"
int ser_cli_tongxing(ser_cli *my_str_staff, int sock_fd)
{
ser_cli my_str_staff_1;
my_str_staff_1.CLI_SELECT = my_str_staff->CLI_SELECT;
my_str_staff_1.staff_information = my_str_staff->staff_information;
int jobnumber = 0;
int pass_w = 0;
OUT1:
printf("输入你的工号:");
scanf("%d", &jobnumber);
user_jobnumber=jobnumber;
if (jobnumber == 0)
{
printf("输入失败,请重新输入%d\n", __LINE__);
goto OUT1;
}
while (getchar() != 10)
;
my_str_staff_1.staff_information.jobnumber = jobnumber;
OUT2:
printf("输入你的密码:");
scanf("%d", &pass_w);
if (jobnumber == 0)
{
printf("输入失败,请重新输入%d\n", __LINE__);
goto OUT2;
}
while (getchar() != 10)
;
my_str_staff_1.staff_information.pass_w = pass_w;
// printf("jobnumber=%d\n",my_str_staff_1.staff_information.jobnumber);
// 账号密码输入完毕,请求服务器登陆
// printf("pass_w=%d\n",my_str_staff_1.staff_information.pass_w);
send(sock_fd, &my_str_staff_1, sizeof(my_str_staff_1), 0);
// 接收信息
if (recv(sock_fd, &my_str_staff_1, sizeof(my_str_staff_1), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
printf("my_str_staff_1.cli_n_p==%d\n", my_str_staff_1.cli_n_p);
// 根据接收到的信息判断
if (my_str_staff_1.cli_n_p == 1)
{
printf("工号不正确,请重新输入\n");
return 0;
}
else if (my_str_staff_1.cli_n_p == 2)
{
printf("密码不正确,请重新输入\n");
return 0;
}
else if (my_str_staff_1.cli_n_p == 3)
{
printf("请从管理员模式登陆\n");
return 0;
}
else if (my_str_staff_1.cli_n_p == 4)
{
printf("员工不得访问root权限\n");
return 0;
}
else if (my_str_staff_1.cli_n_p == 5)
{
if(my_str_staff_1.flag==0)//表示账号重复登陆了
{
printf("你的账号正在登陆中\n");
exit(1);
}
printf("登陆成功 %d\n",__LINE__);
return 1;
}
printf("接收错误\n");
return 0;
}
// 管理员控制界面
int root_ui(ser_cli *my_str_staff)
{
int key = -1;
while (1)
{
printf("<****************************> 1\n");
printf("<*********管理操作系统********> 1\n");
printf("<********1.添加员工信息*******> 1\n");
printf("<********2.修改员工信息*******> 1\n"); // 两种方式 工号 手机号
printf("<********3.查询员工信息*******> 1\n"); // 两种方式 工号 手机号
printf("<********4.查询历史记录*******> 1\n");
printf("<********5.退出管理系统*******> 1\n");
printf("<****************************> 1\n");
printf("\n请选择你要进行的操作:");
scanf("%d", &key);
switch (key)
{
case 1:
add_root_and_user(my_str_staff);
break;
case 2:
root_xiugai_user(my_str_staff); // 修改员工信息
break;
case 3:
chaxun_user(my_str_staff); //root界面和用户界面均能掉
break;
case 4:
root_chaxun_lishi(my_str_staff);
break;
case 5:
my_str_staff->CLI_SELECT_H = 5;
if (send(my_str_staff->fd, my_str_staff, sizeof(*(my_str_staff)), 0) < 0)
{
ERR_MSG("send");
return 0;
}
printf("管理系统退出成功\n");
close(my_str_staff->fd);
exit(1);
break;
default:
printf("输入错误,请重新输入\n");
break;
}
}
}
// 进入用户控制界面
int user_ui(ser_cli *my_str_staff)
{
int key = -1;
while (1)
{
printf("<****************************> 1\n");
printf("<*********员工操作系统********> 1\n");
printf("<********1.查询个人信息*******> 1\n");
printf("<********2.修改个人信息*******> 1\n");
printf("<********3.退出管理系统*******> 1\n");
printf("<****************************> 1\n");
printf("\n请选择你要进行的操作:");
scanf("%d", &key);
switch (key)
{
case 1:
user_chaxun(my_str_staff);
break;
case 2:
user_xiugai(my_str_staff);
break;
case 3:
printf("退出成功\n");
exit(1);
break;
default:
printf("输入错误,请重新输入%d\n", __LINE__);
break;
}
}
}
//员工查询个人信息
int user_chaxun(ser_cli *my_ser_cli_H)
{
printf("员工进入查询界面 line:%d\n",__LINE__);
ser_cli my_ser_cli = *my_ser_cli_H;
my_ser_cli.fd = my_ser_cli_H->fd;
int key = -1;
while (1)
{
printf("查询方式 1<工号> 2.退出查询\n");
printf("请输入>>>>");
scanf("%d", &key);
switch (key)
{
case 1:
my_ser_cli.CLI_SELECT = 1;//高速服务器按照工号查询
my_ser_cli.CLI_SELECT_H=1;//二级界面选项,
my_ser_cli.staff_information.jobnumber=user_jobnumber;
/*输出查询信息*/
root_chaxun_user(&my_ser_cli);
break;
case 2:
printf("用户退出成功\n");
return 0;
break;
default:
printf("输入错误,重新输入%d\n", __LINE__);
break;
}
}
}
//员工修改个人密码
int user_xiugai(ser_cli *my_ser_cli_H)
{
ser_cli my_ser_cli=*my_ser_cli_H;
printf("1<修改密码> 2<退出界面>\n");
int key=-1;
my_ser_cli.CLI_SELECT=1;//告诉服务按照员工号查询后修改
my_ser_cli.CLI_SELECT_H=2;//引导服务器二级界面的选择
my_ser_cli.flag=7;//引导服务器修改密码
my_ser_cli.staff_information.jobnumber=user_jobnumber;
int buf;
printf("请输入>>>>");
scanf("%d",&key);
switch(key)
{
case 1:
printf("修改后的密码>>:");
scanf("%d",&buf);
my_ser_cli.staff_information.pass_w=buf;
xiugai_user_to_ser(&my_ser_cli,7);
break;
case 2:
printf("用户退出成功\n");
return 0;
break;
}
}
//root查询所有历史
int root_chaxun_lishi(ser_cli *my_ser_cli_H)
{
// 重新保存
printf("最多查询当前10位\n");
ser_cli my_ser_cli = *my_ser_cli_H;
ser_cli my_ser_cli_A[10];
my_ser_cli.CLI_SELECT_H = 4; // 提示服务器进入哪一步
if (send(my_ser_cli_H->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("send");
return 0;
}
//接收历史查询信息
printf("size=%ld\n",sizeof(*(my_ser_cli_A)));
if(recv(my_ser_cli_H->fd,my_ser_cli_A,sizeof(*(my_ser_cli_A)),0)<0)
{
ERR_MSG("send");
return 0;
}
for(int i=0;i<my_ser_cli_A->flag+1;i++)
{
printf("1.<<<<工号:%d的信息>>>>>\n",my_ser_cli_A[i].staff_information.jobnumber);
printf("id = %d\n", my_ser_cli_A[i].staff_information.key);
printf("name = %s\n",my_ser_cli_A[i].staff_information.name);
printf("jobnumber = %d\n", my_ser_cli_A[i].staff_information.jobnumber);
printf("age = %d\n", my_ser_cli_A[i].staff_information.age);
printf("wage = %2.f\n", my_ser_cli_A[i].staff_information.wage);
printf("phone = %d\n", my_ser_cli_A[i].staff_information.phone);
printf("time = %s\n", my_ser_cli_A[i].staff_information.time);
printf("state = %d\n", my_ser_cli_A[i].staff_information.state);
printf("pass_w = %d\n", my_ser_cli_A[i].staff_information.pass_w);
printf("\n");
}
printf("查询成功 是否退出(Y/N)\n");
char key;
while(getchar()!=10);
scanf("%c",&key);
while(getchar()!=10);
if(key=='y'||key=='Y')
return 0;
else
{
sleep(10);
}
}
// 添加员工
ser_cli *add_root_and_user(ser_cli *my_ser_cli_ui)
{
ser_cli my_ser_cli;
my_ser_cli.fd = my_ser_cli_ui->fd;
printf("是否为管理1<是> 2<不是>:");
int key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.key = key;
while (getchar() != 10)
;
printf("key=%d\n", my_ser_cli.staff_information.key);
printf("输入员工姓名:");
char name[128] = "";
scanf("%s", name);
printf("name=%s", name);
strcpy(my_ser_cli.staff_information.name, name);
while (getchar() != 10)
;
printf("name=%s\n", my_ser_cli.staff_information.name);
printf("输入员工工号:");
key = -1;
scanf("%d", &key);
if (key == 0)
{
printf("工号不可为0\n");
}
my_ser_cli.staff_information.jobnumber = key;
while (getchar() != 10)
;
printf("jobnumber=%d\n", my_ser_cli.staff_information.jobnumber);
printf("输入员工年龄:");
key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.age = key;
while (getchar() != 10)
;
printf("age=%d\n", my_ser_cli.staff_information.age);
printf("输入员工薪资:");
float wage = -1;
scanf("%f", &wage);
my_ser_cli.staff_information.wage = key;
while (getchar() != 10)
;
printf("wage=%f\n", my_ser_cli.staff_information.wage);
printf("输入员工岗位:");
char post[128] = "";
scanf("%s", post);
strcpy(my_ser_cli.staff_information.post, post);
while (getchar() != 10)
;
printf("post=%s\n", my_ser_cli.staff_information.post);
printf("输入员工手机:");
key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.phone = key;
while (getchar() != 10)
;
printf("key=%d\n", my_ser_cli.staff_information.phone);
printf("输入员工入职时间:");
scanf("%s", post);
strcpy(my_ser_cli.staff_information.time, post);
printf("time=%s\n", my_ser_cli.staff_information.time);
printf("输入员工密码:");
key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.pass_w = key;
while (getchar() != 10)
;
printf("pass_w=%d\n", my_ser_cli.staff_information.pass_w);
my_ser_cli.staff_information.state = 0;
my_ser_cli.CLI_SELECT_H = 1; // 添加员工信息指令码
printf("state=%d\n", my_ser_cli.staff_information.state);
printf("send fd =%d %d\n", my_ser_cli_ui->fd, __LINE__);
if (send(my_ser_cli_ui->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("send");
return 0;
}
// 接收消息是否添加成功
my_ser_cli.CLI_SELECT = 0;
if (recv(my_ser_cli_ui->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
// 服务器发来标志位,判断账号是否存在为1
if (my_ser_cli.CLI_SELECT == 1)
{
printf("该工号已经存在 %d\n", __LINE__);
return 0;
}
if (my_ser_cli.staff_information.jobnumber)
{
printf("员工添加信息成功 %d\n", __LINE__);
}
}
// root修改员工信息,将修改的数据发送到服务器
int xiugai_user_to_ser(ser_cli *my_str_staff, int key)
{
// 重新保存
ser_cli my_ser_cli = *my_str_staff;
my_ser_cli.CLI_SELECT_H = 2; // 提示服务器进入哪一步
printf("key=%d\n", key);
printf("pass_w=%d %d\n",my_ser_cli.staff_information.pass_w,__LINE__);
if (send(my_str_staff->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("send");
return 0;
}
// 接收消息是否修改成功,先改变为失败标志
my_ser_cli.CLI_SELECT = 1;
if (recv(my_str_staff->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
// 服务器发来标志,如果成功则将SELECT修改为0,否则提示其搜索失败
if (my_ser_cli.CLI_SELECT != 0)
{
if (my_str_staff->CLI_SELECT == 1)
{
printf("按员工账号搜索失败\n");
}
if (my_str_staff->CLI_SELECT == 2)
{
printf("按手机号码搜索失败\n");
}
return 0;
}
else
{
printf("员工信息修改成功\n");
}
// 走到这里表示修改成功
return 1;
}
// root修改员工信息
ser_cli *root_xiugai_user(ser_cli *my_str_staff)
{
ser_cli my_ser_cli;
my_ser_cli.fd = my_str_staff->fd;
int key = -1;
int key_flag;
printf("只能修改用户信息\n");
while (1)
{
key = -1;
printf("1:按照员号修改 2:按照手机号码修改 3:退出\n");
printf("*请输入你的查找方式*:");
scanf("%d", &key);
my_ser_cli.CLI_SELECT = key; // 1按照员工号 2按照手机号
while (getchar() != 10)
;
switch (key)
{
case 1:
printf("输入员工工号:");
key = -1;
scanf("%d", &key);
if (key == 0)
{
printf("工号不可为0\n");
}
my_ser_cli.staff_information.jobnumber = key;
while (getchar() != 10)
;
printf("1<姓名> 2<年龄> 3<薪水>n 4<岗位> ");
printf("5<手机号> 6<入职时间> 7<密码>\n");
key = -1;
printf("*请输入你想修改的信息*:");
scanf("%d", &key);
key_flag=key;
my_ser_cli.flag=key_flag;
switch (key)
{
case 1:
printf("输入员工姓名:");
char name[128] = "";
scanf("%s", name);
printf("name=%s", name);
strcpy(my_ser_cli.staff_information.name, name);
while (getchar() != 10)
;
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 2:
printf("输入员工年龄:");
key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.age = key;
while (getchar() != 10)
;
printf("age=%d\n", my_ser_cli.staff_information.age);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 3:
printf("输入员工薪资:");
float wage = -1;
scanf("%f", &wage);
my_ser_cli.staff_information.wage = key;
while (getchar() != 10)
;
printf("wage=%f\n", my_ser_cli.staff_information.wage);
// 为服务器提供是修改哪一项
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 4:
printf("输入员工岗位:");
char post[128] = "";
scanf("%s", post);
strcpy(my_ser_cli.staff_information.post, post);
while (getchar() != 10)
;
printf("post=%s\n", my_ser_cli.staff_information.post);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 5:
printf("输入员工手机:");
key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.phone = key;
while (getchar() != 10)
;
printf("key=%d\n", my_ser_cli.staff_information.phone);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 6:
printf("输入员工入职时间:");
scanf("%s", post);
strcpy(my_ser_cli.staff_information.time, post);
printf("time=%s\n", my_ser_cli.staff_information.time);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 7:
printf("输入员工密码:");
key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.pass_w = key;
while (getchar() != 10)
;
printf("pass_w=%d\n", my_ser_cli.staff_information.pass_w);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
default:
printf("输入错误,重新输入\n");
break;
}
break;
case 2:
my_ser_cli.CLI_SELECT = 2;
printf("输入员工手机:");
key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.key = key; // 手机号用key暂时保存
while (getchar() != 10)
;
printf("key=%d\n", my_ser_cli.staff_information.key);
printf("1<姓名> 2<年龄> 3<薪水>n 4<岗位> ");
printf("5<手机号> 6<入职时间> 7<密码>\n");
printf("*请输入你想修改的信息*:");
key = -1;
scanf("%d", &key);
key_flag=key;
my_ser_cli.flag=key_flag;
switch (key)
{
case 1:
printf("输入员工姓名:");
char name[128] = "";
scanf("%s", name);
printf("name=%s", name);
strcpy(my_ser_cli.staff_information.name, name);
while (getchar() != 10)
;
printf("name=%s\n", my_ser_cli.staff_information.name);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 2:
printf("输入员工年龄:");
key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.age = key;
while (getchar() != 10)
;
printf("age=%d\n", my_ser_cli.staff_information.age);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 3:
printf("输入员工薪资:");
float wage = -1;
scanf("%f", &wage);
my_ser_cli.staff_information.wage = wage;
while (getchar() != 10)
;
printf("wage=%f\n", my_ser_cli.staff_information.wage);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 4:
printf("输入员工岗位:");
char post[128] = "";
scanf("%s", post);
strcpy(my_ser_cli.staff_information.post, post);
while (getchar() != 10)
;
printf("post=%s\n", my_ser_cli.staff_information.post);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 5:
printf("输入员工手机:");
key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.phone = key;
while (getchar() != 10)
;
printf("key=%d\n", my_ser_cli.staff_information.phone);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 6:
printf("输入员工入职时间:");
scanf("%s", post);
strcpy(my_ser_cli.staff_information.time, post);
printf("time=%s\n", my_ser_cli.staff_information.time);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
case 7:
printf("输入员工密码:");
key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.pass_w = key;
while (getchar() != 10)
;
printf("pass_w=%d\n", my_ser_cli.staff_information.pass_w);
if (xiugai_user_to_ser(&my_ser_cli, key) < 0)
{
return 0;
}
break;
default:
printf("输入错误,重新输入%d\n", __LINE__);
break;
}
break;
case 3:
printf("key=%d 退出修改%d\n", key, __LINE__);
return 0;
break;
default:
printf("输入错误,重新输入%d\n", __LINE__);
break;
}
}
}
// root查询员工的信息选择
int chaxun_user(ser_cli *my_ser_cli_H)
{
ser_cli my_ser_cli = *my_ser_cli_H;
my_ser_cli.fd = my_ser_cli_H->fd;
printf("root进入员工查询\n");
int key = -1;
while (1)
{
printf("查询方式 1<工号> 2.手机号 3.退出查询\n");
printf("请输入>>>>");
scanf("%d", &key);
switch (key)
{
case 1:
my_ser_cli.CLI_SELECT = 1;
printf("<<<按照工号查询>>>\n");
key = -1;
scanf("%d", &key);
if (key == 0)
{
printf("工号不可为0\n");
}
my_ser_cli.staff_information.jobnumber = key;
while (getchar() != 10)
;
printf("jobnumber=%d\n", my_ser_cli.staff_information.jobnumber);
/*输出查询信息*/
if(root_chaxun_user(&my_ser_cli)<0)
{
break;
}
break;
case 2:
printf("<<<按照手机号查询>>>\n");
my_ser_cli.CLI_SELECT = 2;
printf("输入员工手机:");
key = -1;
scanf("%d", &key);
my_ser_cli.staff_information.phone = key; // 手机号用key暂时保存
while (getchar() != 10)
;
printf("key=%d\n", my_ser_cli.staff_information.key);
/*输出查询信息*/
if(root_chaxun_user(&my_ser_cli)<0)
{
break;
}
break;
case 3:
printf("<<<退出成功>>>\n");
return 0;
break;
default:
printf("输入错误,重新输入%d\n", __LINE__);
break;
}
}
}
//root查询的功能
int root_chaxun_user(ser_cli *my_ser_cli_H)
{
//按照SELECT的值判断根据什么查找
// 重新保存
ser_cli my_ser_cli = *my_ser_cli_H;
if(my_ser_cli.staff_information.key==1)//判断是用户还是root
my_ser_cli.CLI_SELECT_H = 3; // 提示服务器进入哪一步
else if(my_ser_cli.staff_information.key==2)//员工
my_ser_cli.CLI_SELECT_H=1;
if (send(my_ser_cli_H->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("send");
return 0;
}
// 接收消息是否查询成功,先改变为失败标志
my_ser_cli.CLI_SELECT = 1;
if (recv(my_ser_cli_H->fd, &my_ser_cli, sizeof(my_ser_cli), 0) < 0)
{
ERR_MSG("recv");
return 0;
}
// 服务器发来标志,如果成功则将SELECT修改为0,否则提示其搜索失败
if (my_ser_cli.CLI_SELECT != 0)
{
if (my_ser_cli_H->CLI_SELECT == 1)
{
printf("按员工账号查找失败\n");
}
if (my_ser_cli_H->CLI_SELECT == 2)
{
printf("按手机号码查找失败\n");
}
return 0;
}
if(my_ser_cli.CLI_SELECT==0)
{
//先打印查询成功的信息
printf("id = %d\n", my_ser_cli.staff_information.key);
printf("name = %s\n",my_ser_cli.staff_information.name);
printf("jobnumber = %d\n", my_ser_cli.staff_information.jobnumber);
printf("age = %d\n", my_ser_cli.staff_information.age);
printf("wage = %2.f\n", my_ser_cli.staff_information.wage);
printf("phone = %d\n", my_ser_cli.staff_information.phone);
printf("time = %s\n", my_ser_cli.staff_information.time);
printf("state = %d\n", my_ser_cli.staff_information.state);
printf("pass_w = %d\n", my_ser_cli.staff_information.pass_w);
printf("<<<<<<员工信息查找成功>>>>>\n");
}
// 走到这里表示修改成功
return 1;
}
2.3客户端头文件
#ifndef __CLIENT_H__
#define __CLIENT_H__
/******头文件区域*******/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/epoll.h>
#include <sqlite3.h>
#include <pthread.h>
/******引用区域*******/
// 创建数据库并打开数据表
sqlite3 * Sqlite_Create(void);
// 服务器 套接字->端口重启->绑定->监听
int sock_listen(void);
// 红黑树监听事件信息的添加
int add_epoll(int epfd, int fd);
//添加线程管理交互界面
void *callBack(void *arg);
#define DEBUG_LINE printf("Debug line:%d\n",__LINE__)
// 错误码
#define ERR_MSG(msg) \
do \
{ \
fprintf(stderr, "line:%d ", __LINE__); \
perror(msg); \
} while (0)
#define PORT 6666 // 服务器端口
#define IP "192.168.250.100" // 服务器IP地址
#define MAX 10 //顺序表最大容量
// 信息结构体,因为使用IPv4,因此使用sockaddr_in填充bind的第二个参数
struct sockaddr_in my_ser; // 服务器信息结构体
struct sockaddr_in my_cin; // 保存客户端信息结构体
// 员工信息结构体
typedef struct staff
{
int key; // 判断是用户还是管理员 1是管理 2是用户
char name[128]; // 员工姓名
int jobnumber; // 员工工号
int age; // 员工年龄
float wage; // 当前的薪资
char post[128]; // 岗位名称
int phone; // 手机号
char time[128]; // 精确到日,入职时间
int state; // 是否在线 1表示在线
int pass_w; // 密码
} str_staff;
// 服务器与客户端通信的结构体
typedef struct info
{
int fd;//客户端的描述符
int CLI_SELECT; // 登陆时选择的操作 1管理员登陆,2是用户登陆 3是退出
int CLI_SELECT_H; //登陆后选择的操作 1.查询信息 2.修改密码 3.查询记录
int events_i; //保存红黑树数组的下标
int cli_n_p; //高账号密码权力的匹配程度,1表示账号不存在2表示密码不正确3表示不是特权4表示不是用户5均成功
int flag;//进入2级界面选项后,传递的自定义标志位
sqlite3 *db;
str_staff staff_information; // 员工信息结构体
} ser_cli;
//客户端发送信息
int ser_cli_tongxing(ser_cli * my_str_staff,int sock_fd);
int root_ui(ser_cli *my_str_staff);
int user_ui(ser_cli *my_ser_staff);
//添加员工信息
ser_cli *add_root_and_user(ser_cli *my_ser_cli_ui);
//修改员工信息
ser_cli *root_xiugai_user(ser_cli *my_str_staff);
//修改员工信息后与服务器通信
int xiugai_user_to_ser(ser_cli *my_str_staff,int key);
//root查询员工信息
int chaxun_user(ser_cli * my_str_staff);
int root_chaxun_user(ser_cli *my_str_staff); //输出查询到的结果
//root查询历史表
int root_chaxun_lishi(ser_cli *my_ser_cli_H);
//用户查询个人信息
int user_chaxun(ser_cli *my_ser_cli_H);
//用户修改个人密码
int user_xiugai(ser_cli *my_ser_cli_H);
typedef struct newfd
{
int fd;
}my_fd;
typedef struct fd_1
{
my_fd arr[MAX];
int len;
}str_newfd;
// 保存就绪事件的信息,用于移植到红黑树中
struct epoll_event event;
// 存放就绪事件描述符的数组
struct epoll_event events[10];
int user_jobnumber;//保存客户顿的user工号
#endif
3.Makefile
CC = gcc
CFLAGS = -Wextra
LDFLAGS = -lsqlite3 -pthread
SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))
TARGET = program
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJ) $(TARGET)
文章来源地址https://www.toymoban.com/news/detail-621703.html
文章来源:https://www.toymoban.com/news/detail-621703.html
到了这里,关于基于数据库 Sqlite3 的 root 管理系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!