1.服務器
1.1服務器函數(shù)入口
#include "server.h"
int main(int argc, char const *argv[])
{
char buf[128] = {0};
char buf_ID[256] = {0};
// 接收報錯信息判斷
sqlite3 *db;
// 創(chuàng)建員工信息的表格,存在則打開
db = Sqlite_Create();
if (db == NULL)
{
printf("sqlite_create=NULL\n");
return 0;
}
// 服務器 套接字->端口重啟->綁定->監(jiān)聽
int sock_fd = sock_listen();
if (!sock_fd)
{
printf("流程出現(xiàn)故障%d\n", __LINE__);
return 0;
}
// 創(chuàng)建紅黑樹根節(jié)點
// 創(chuàng)建一個epoll句柄/紅黑樹根節(jié)點
epfd = epoll_create(10);
if (epfd < 0)
{
printf("epoll_create on_success _%d_", __LINE__);
return 0;
}
// 添加監(jiān)聽連接事件到紅黑樹節(jié)點中
add_epoll(epfd, sock_fd);
// 到此,以上流程全部正確走完
// 客戶端信息結(jié)構體的大小
socklen_t addrlen = sizeof(my_cin);
/*********與客戶端互動區(qū)域_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返回就緒事件的個數(shù),并將就緒的事件放入到
// events這個結(jié)構體中,參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++)
{
// 客戶端連接事件發(fā)生
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;
// 創(chuàng)建一個線程
pthread_t tid;
my_ser_cli.fd = events[i].data.fd;
// 接收客戶端數(shù)據(jù),進入賬號密碼的判斷,是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登陸
// 當事件發(fā)生以后移除文件描述符
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線程創(chuàng)建失敗%d\n", tid, __LINE__);
return 0;
}
remove_fd(&my_ser_cli);//賬號下線,清楚其存在
}
}
}
/*********與客戶端互動區(qū)域_end*********/
// 釋放資源
return 0;
}
1.2服務器運行代碼
#include "server.h"
int flag = 0;
int fd_flag = 0;
// 創(chuàng)建數(shù)據(jù)庫并打開數(shù)據(jù)表
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;
// 創(chuàng)建并打開數(shù)據(jù)庫
sqlite3 *db = NULL;
if (sqlite3_open("./staff.db", &db) != SQLITE_OK)
{
printf("sqlite3_open errno %d\n", __LINE__);
return NULL;
}
debuf_db = db;
// 組裝SQL語句創(chuàng)建數(shù)據(jù)表
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;
}
// 服務器 套接字->端口重啟->綁定->監(jiān)聽
int sock_listen(void)
{
// 一.創(chuàng)建套接字1.AF_INET默認為ip(7)協(xié)議 2.SOCK_STREAM默認為TCP
// 3.0表示使用type對應的默認協(xié)議
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;
}
// 填充服務器信息結(jié)構體
my_ser.sin_family = AF_INET; // IPv4協(xié)議指向填充
my_ser.sin_port = htons(PORT); // 將端口轉(zhuǎn)換成網(wǎng)絡字節(jié)
my_ser.sin_addr.s_addr = inet_addr(IP); // IP地址轉(zhuǎn)換成網(wǎng)絡字節(jié)序
// 綁定服務器的IP和端口
if (bind(sock_fd, (struct sockaddr *)&my_ser, sizeof(my_ser)) < 0)
{
ERR_MSG("bind");
goto OUT2;
}
// 將套接字設置為被動監(jiān)聽,最多監(jiān)聽128個
if (listen(sock_fd, 128) < 0)
{
ERR_MSG("listen");
goto OUT2;
}
return sock_fd;
OUT2:
close(sock_fd);
OUT1:
return 0;
}
// 紅黑樹監(jiān)聽事件信息的添加
int add_epoll(int epfd, int fd)
{
// 將套接字的信息存入到event結(jié)構體中,為事件放入紅黑樹中做準備
event.events = EPOLLIN; // 關注可讀事件,套接字有數(shù)據(jù)可讀時觸發(fā)
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結(jié)構體中,為事件放入紅黑樹中做準備
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.)
// }
// }
// 資源的釋放函數(shù)
// 創(chuàng)建一個線程處理客戶端交互
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;
// 將員工號存到數(shù)組里,用于歷史記錄查詢
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);
// 判斷該賬號是否以及存在于數(shù)組
for (int i = 0; i < 10; i++)
{
if (jobnumber_A[i].staff_information.jobnumber == my_ser_cli.staff_information.jobnumber) // 已經(jīng)在數(shù)組中
{
return 0; // 不做添加
}
}
// 走到這里表示該賬號不存在數(shù)組中,添加
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) // 表示工號已經(jīng)存在
{
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); // 發(fā)送歷史查詢記錄
break;
case 5:
printf("管理系統(tǒng)退出成功\n");
return 0;
break;
default:
printf("輸入錯誤,請重新輸入\n");
return 0;
break;
}
}
}
// 服務器向root發(fā)送歷史記錄表
int root_lishi_user(ser_cli *my_ser_cli_H)
{
printf("root調(diào)用歷史信息表\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++)
{
// 將存在的所有放到數(shù)組里面
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) // 表示沒有找到,向服務器發(fā)送信息
{
printf("出現(xiàn)錯誤 工號不存在%d\n", __LINE__);
}
else
{
// 走到這里表示工號存在,將員工信息填充發(fā)送帶客戶端
// 發(fā)送
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("歷史記錄表成功發(fā)送\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) // 表示沒有找到,向服務器發(fā)送信息
{
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
{
// 走到這里表示工號存在,將員工信息填充發(fā)送帶客戶端
// 發(fā)送
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) // 表示沒有找到,向服務器發(fā)送信息
{
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,則修改成功
// 判斷是根據(jù)<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) // 表示沒有找到,向服務器發(fā)送信息
{
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 // 走到這里,表示根據(jù)員工號找到對應的員工信息
{
key = 1;
// 根據(jù)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) // 如果為假,表示失敗,發(fā)送失敗給客戶端
{
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) // 表示沒有找到,向服務器發(fā)送信息
{
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 // 走到這里,表示根據(jù)員工號找到對應的員工信息
{
key = 1;
// 根據(jù)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) // 如果為假,表示失敗,發(fā)送失敗給客戶端
{
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: // 退出管理系統(tǒng)
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;
// 用戶登錄后添加賬號信息到數(shù)組中,判斷是否在線
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__
/******頭文件區(qū)域*******/
#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>
/******引用區(qū)域*******/
// 創(chuàng)建數(shù)據(jù)庫并打開數(shù)據(jù)表
sqlite3 * Sqlite_Create(void);
// 服務器 套接字->端口重啟->綁定->監(jiān)聽
int sock_listen(void);
// 紅黑樹監(jiān)聽事件信息的添加
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 //順序表最大容量
// 信息結(jié)構體,因為使用IPv4,因此使用sockaddr_in填充bind的第二個參數(shù)
struct sockaddr_in my_ser; // 服務器信息結(jié)構體
struct sockaddr_in my_cin; // 保存客戶端信息結(jié)構體
// 員工信息結(jié)構體
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;
// 服務器與客戶端通信的結(jié)構體
typedef struct info
{
int fd;//客戶端的描述符
int CLI_SELECT; // 登陸時選擇的操作 1管理員登陸,2是用戶登陸 3是退出
int CLI_SELECT_H; //登陸后選擇的操作 1.添加員工信息 2.修改員工記錄 3.查詢員工記 4.查詢歷史 5,退出管理
int events_i; //保存紅黑樹數(shù)組的下標
int cli_n_p; //高賬號密碼權力的匹配程度,1表示賬號不存在2表示密碼不正確3表示不是特權4表示不是用戶5均成功
int flag;//進入2級界面選項后,傳遞的自定義標志位
sqlite3 *db;
str_staff staff_information; // 員工信息結(jié)構體
} ser_cli;
//客戶端發(fā)送信息
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);
//添加員工信息到數(shù)組中
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);
//退出函數(shù)
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;
// 存放就緒事件描述符的數(shù)組
sqlite3 * debuf_db;
struct epoll_event events[10];
pthread_t tid;
int fd_A[10];
ser_cli jobnumber_A[10];
int epfd ;//紅黑樹根節(jié)點
#endif
2.客戶端代碼
2.1客戶端函數(shù)入口
#include "client.h"
int main(int argc, char const *argv[])
{
// 創(chuàng)建套接字
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; //通信結(jié)構體
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:
// 改變對應的結(jié)構體信息
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:
// 改變對應的結(jié)構體信息
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:
// 改變對應的結(jié)構體信息
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客戶端執(zhí)行代碼
#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);
// 根據(jù)接收到的信息判斷
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("你的賬號正在登陸中\(zhòng)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("<*********管理操作系統(tǒng)********> 1\n");
printf("<********1.添加員工信息*******> 1\n");
printf("<********2.修改員工信息*******> 1\n"); // 兩種方式 工號 手機號
printf("<********3.查詢員工信息*******> 1\n"); // 兩種方式 工號 手機號
printf("<********4.查詢歷史記錄*******> 1\n");
printf("<********5.退出管理系統(tǒng)*******> 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("管理系統(tǒng)退出成功\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("<*********員工操作系統(tǒng)********> 1\n");
printf("<********1.查詢個人信息*******> 1\n");
printf("<********2.修改個人信息*******> 1\n");
printf("<********3.退出管理系統(tǒng)*******> 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;
}
// 服務器發(fā)來標志位,判斷賬號是否存在為1
if (my_ser_cli.CLI_SELECT == 1)
{
printf("該工號已經(jīng)存在 %d\n", __LINE__);
return 0;
}
if (my_ser_cli.staff_information.jobnumber)
{
printf("員工添加信息成功 %d\n", __LINE__);
}
}
// root修改員工信息,將修改的數(shù)據(jù)發(fā)送到服務器
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;
}
// 接收消息是否修改成功,先改變?yōu)槭酥? 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;
}
// 服務器發(fā)來標志,如果成功則將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的值判斷根據(jù)什么查找
// 重新保存
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;
}
// 接收消息是否查詢成功,先改變?yōu)槭酥? 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;
}
// 服務器發(fā)來標志,如果成功則將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__
/******頭文件區(qū)域*******/
#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>
/******引用區(qū)域*******/
// 創(chuàng)建數(shù)據(jù)庫并打開數(shù)據(jù)表
sqlite3 * Sqlite_Create(void);
// 服務器 套接字->端口重啟->綁定->監(jiān)聽
int sock_listen(void);
// 紅黑樹監(jiān)聽事件信息的添加
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 //順序表最大容量
// 信息結(jié)構體,因為使用IPv4,因此使用sockaddr_in填充bind的第二個參數(shù)
struct sockaddr_in my_ser; // 服務器信息結(jié)構體
struct sockaddr_in my_cin; // 保存客戶端信息結(jié)構體
// 員工信息結(jié)構體
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;
// 服務器與客戶端通信的結(jié)構體
typedef struct info
{
int fd;//客戶端的描述符
int CLI_SELECT; // 登陸時選擇的操作 1管理員登陸,2是用戶登陸 3是退出
int CLI_SELECT_H; //登陸后選擇的操作 1.查詢信息 2.修改密碼 3.查詢記錄
int events_i; //保存紅黑樹數(shù)組的下標
int cli_n_p; //高賬號密碼權力的匹配程度,1表示賬號不存在2表示密碼不正確3表示不是特權4表示不是用戶5均成功
int flag;//進入2級界面選項后,傳遞的自定義標志位
sqlite3 *db;
str_staff staff_information; // 員工信息結(jié)構體
} ser_cli;
//客戶端發(fā)送信息
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); //輸出查詢到的結(jié)果
//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;
// 存放就緒事件描述符的數(shù)組
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)
文章來源地址http://www.zghlxwxcb.cn/news/detail-621703.html
文章來源:http://www.zghlxwxcb.cn/news/detail-621703.html
到了這里,關于基于數(shù)據(jù)庫 Sqlite3 的 root 管理系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!