head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/select.h>
#include <poll.h>
#include <errno.h>
#include <sqlite3.h>
#include <sys/epoll.h>
#define PRINT_ERR(msg) \
do{\
fprintf(stderr,"line:%d ",__LINE__);\
perror(msg);\
return -1;\
} while(0)
#define IF(i) if (argc != i) {\
printf("input error,try again\n");\
printf("usage: ./a.out srcfile destfile\n");\
return -1;\
}
#endif
serverhead.h
#ifndef __SERVREHEAD_H_
#define __SERVERHEAD_H_
#define PORT 8888
#define IP "192.168.100.88"
struct td
{
int newfd;
struct sockaddr_in cin_t;
};
typedef struct staff_info
{
char worknumber[10]; // 员工编号
char name[10]; // 姓名
char passwd[10]; // 密码
char age[5]; // 年龄
char phone[15]; // 电话
char addr[40]; // 地址
char work[20]; // 职位
char date[30]; // 入职时间
char level[2]; // 等级
double salary; // 工资
} staff_info_t;
typedef struct
{
int msgtype; // 请求的消息类型
char worknumber[20]; // 员工编号
char level; // 等级
char recvmsg[256]; // 通信的消息
int flags; // 标志位
staff_info_t info; // 员工信息
} MSG;
void *request(void *arg);
sqlite3 *init_sql();
int Users_logoff();
int init_tcpser(char *ip, int port);
int IsuserExist(char *name);
char getusrlevel(char *name);
int Login(int sfd);
int User_isonline(char *name);
int User_online(char *name);
int User_logoff();
int Register(int sfd);
int Delete(int sfd);
int Update(int sfd);
int Query(int sfd);
int do_select(int sfd);
int do_history(char *event);
char *gettime();
int select_history(int sfd);
#endif
cilend.h
#ifndef __CLIENDHEAD_H_
#define __CLIENDHEAD_H_
#define PORT 8888
#define IP "192.168.100.88"
struct td
{
int newfd;
struct sockaddr_in cin_t;
};
typedef struct staff_info
{
char worknumber[10]; // 员工编号
char name[10]; // 姓名
char passwd[10]; // 密码
char age[5]; // 年龄
char phone[15]; // 电话
char addr[40]; // 地址
char work[20]; // 职位
char date[30]; // 入职时间
char level[2]; // 等级
double salary; // 工资
} staff_info_t;
typedef struct
{
int msgtype; // 请求的消息类型
char worknumber[20]; // 员工编号
char level; // 等级
char recvmsg[256]; // 通信的消息
int flags; // 标志位
staff_info_t info; // 员工信息
} MSG;
typedef void (*sighandler_t)(int);
void handler(int sig);
int init_tcpcli(char *ip, int port);
int Login_page(int sfd);
int main_page_root(int sfd);
int main_page_ordinary(int sfd);
int Login(int sfd);
int Register(int sfd);
int Delete(int sfd);
int Update(int sfd);
int Query(int sfd);
int dict_select(int sfd);
int select_history(int sfd);
int end(int sfd);
#endif
###tcpser_staff.c
#include <head.h>
#include "serverhead.h"
staff_info_t info;
MSG msg;
int const size = sizeof(msg);
//存放日志信息
char event[400];
sqlite3 *db;
int epfd;
//事件的集合
struct epoll_event events[20];
int main(int argc, const char *argv[])
{
int epct;
// 初始化数据库
db = init_sql();
// 初始化tcp服务器
int sfd = init_tcpser(IP, PORT);
// 存储客户端信息
struct td td_t, td_s[20];
// 消息结构体大小
socklen_t addrlen = sizeof(struct sockaddr_in);
// 使用epoll进行IO多路复用
struct epoll_event event;
epfd = epoll_create(1);
event.events = EPOLLIN;
event.data.fd = sfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &event) < 0)
PRINT_ERR("epoll_ctl");
while (1)
{
epct = epoll_wait(epfd, events, 20, -1);
for (int i = 0; i < epct; i++)
{
if (events[i].data.fd == sfd)
{ // 如果事件的fd是监听fd,调用accept处理
td_t.newfd = accept(sfd, (struct sockaddr *)&td_t.cin_t, &addrlen);
if (td_t.newfd < 0)
PRINT_ERR("accept");
event.events = EPOLLIN;
event.data.fd = td_t.newfd;
// 添加clientfd描述符
epoll_ctl(epfd, EPOLL_CTL_ADD, td_t.newfd, &event);
printf("[%s:%d] newfd:%d 成功连接\n", inet_ntoa(td_t.cin_t.sin_addr), ntohs(td_t.cin_t.sin_port), td_t.newfd);
td_s[td_t.newfd].newfd = td_t.newfd;
td_s[td_t.newfd].cin_t = td_t.cin_t;
}
else
{
request((void *)&td_s[events[i].data.fd]);
}
}
}
close(sfd);
return 0;
}
// 处理请求函数
void *request(void *arg)
{
struct td *p = (struct td *)arg;
int newfd = p->newfd;
struct sockaddr_in cin_t = p->cin_t;
ssize_t res;
res = recv(newfd, &msg, size, 0);
if (res == 0)
{
printf("客户端断开,关闭newfd:%d\n", newfd);
//删除监听的文件描述符
epoll_ctl(epfd, EPOLL_CTL_DEL, newfd,NULL);
close(newfd);
return NULL;
}
switch (msg.msgtype)
{
case 1:
printf("[%s:%d] newfd:%d请求注册\n", inet_ntoa(cin_t.sin_addr),
ntohs(cin_t.sin_port), newfd);
Register(newfd);
//导入日志信息
do_history(event);
break;
case 2:
printf("[%s:%d] newfd:%d请求登录\n", inet_ntoa(cin_t.sin_addr),
ntohs(cin_t.sin_port), newfd);
Login(newfd);
do_history(event);
break;
case 3:
printf("[%s:%d] newfd:%d请求删除员工\n", inet_ntoa(cin_t.sin_addr),
ntohs(cin_t.sin_port), newfd);
Delete(newfd);
do_history(event);
break;
case 4:
printf("[%s:%d] newfd:%d请求修改员工信息\n", inet_ntoa(cin_t.sin_addr),
ntohs(cin_t.sin_port), newfd);
Update(newfd);
do_history(event);
break;
case 5:
printf("[%s:%d] newfd:%d准备下线\n", inet_ntoa(cin_t.sin_addr),
ntohs(cin_t.sin_port), newfd);
User_logoff();
do_history(event);
break;
case 6:
printf("[%s:%d] newfd:%d查询个人信息\n", inet_ntoa(cin_t.sin_addr),
ntohs(cin_t.sin_port), newfd);
Query(newfd);
do_history(event);
break;
case 7:
printf("[%s:%d] newfd:%d查询所有信息\n", inet_ntoa(cin_t.sin_addr),
ntohs(cin_t.sin_port), newfd);
Query(newfd);
do_history(event);
break;
case 8:
printf("[%s:%d] newfd:%d查看日志信息\n", inet_ntoa(cin_t.sin_addr),
ntohs(cin_t.sin_port), newfd);
select_history(newfd);
do_history(event);
break;
default:
break;
}
}
// 初始化数据库
sqlite3 *init_sql()
{
if (sqlite3_open("sql.db", &db) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_open:%s\n", __LINE__, sqlite3_errmsg(db));
return NULL;
}
//添加日志表
char sql[256] = "create table if not exists history (time char,worknumber char,event char);";
char *errmsg = NULL;
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return NULL;
}
//添加用户表
strcpy(sql, "create table if not exists usr (worknumber char primary key,password char,name char,age char,phone char,addr char,work char,time char,level char,salary double,flag char);");
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return NULL;
}
// 将所有用户置于下线状态
Users_logoff();
printf("数据库初始化完毕\n");
return db;
}
// 添加管理员将所有用户置于下线状态
int Users_logoff()
{
char sql[128];
// 将所有用户flag置零
char *errmsg = NULL;
sprintf(sql, "UPDATE usr SET flag='0';");
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
// 检查是否已有管理员
sprintf(sql, "select * from usr where worknumber='%s';", "00");
char **pres;
int row, column;
if (sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
sqlite3_free_table(pres);
if (row == 0)
{
// 添加一名管理员
char time[30];
strcpy(time, gettime());
time[10] = '\0';
sprintf(sql, "INSERT INTO usr VALUES (\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%-10s\",\"%s\",%f,\"%s\");", "00", "123456", "zt", "21", "19856602562", "hqyj", "CEO", time, "0", 12000.00, "0");
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
printf("添加管理员成功\n");
}
return 0;
}
// 判断用户是否存在
int IsuserExist(char *name)
{
char sql[128];
char *errmsg = NULL;
sprintf(sql, "select * from usr where worknumber='%s';", name);
char **pres;
int row, column;
if (sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
sqlite3_free_table(pres);
// row=0,即没有查询结果,不存在用户
return (row != 0) ? 1 : 0;
}
// 获取用户等级
char getusrlevel(char *name)
{
char sql[128];
char *errmsg = NULL;
sprintf(sql, "select level from usr where worknumber='%s';", name);
char **pres;
int row, column;
if (sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return 0;
}
sqlite3_free_table(pres);
return *pres[1];
}
// 初始化tcp服务器
int init_tcpser(char *ip, int port)
{
// 创建流式套接字
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd < 0)
PRINT_ERR("socket");
// 允许端口快速重用
int reuse = 1;
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
PRINT_ERR("setsockopt");
// 填充地址信息的结构体,将IP和端口号绑定到套接字上
struct sockaddr_in sin_t;
sin_t.sin_family = AF_INET;
sin_t.sin_port = htons(port);
sin_t.sin_addr.s_addr = inet_addr(ip);
// 绑定服务器的ip和端口
if (bind(sfd, (struct sockaddr *)&sin_t, sizeof(sin_t)) < 0)
PRINT_ERR("bind");
// 将套接字设置为监听状态
if (listen(sfd, 128) < 0)
PRINT_ERR("listen");
printf("服务器初始化完成\n");
return sfd;
}
// 客户端登录
int Login(int sfd)
{
printf("工号:%s 密码:%s\n", msg.info.worknumber, msg.info.passwd);
char sql[128];
char *errmsg = NULL;
sprintf(sql, "select * from usr where worknumber='%s';", msg.info.worknumber);
char **pres;
int row, column;
if (sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
// row=0,即没有查询结果,不存在用户
if (row == 0)
{
strcpy(event, "登录失败,不存在该用户");
// 不存在该用户发送0
printf("不存在该用户\n");
msg.flags = -2;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
}
// 判断密码是否相同
else if (strcmp(pres[12], msg.info.passwd) == 0)
{
// 判断用户是否在线
if (User_isonline(msg.info.worknumber) == 1)
{ // 用户已在线发送3
msg.flags = -4;
strcpy(event, "登录失败,用户已在线");
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
return -1;
}
// 将用户flag置1
User_online(msg.info.worknumber);
//获取用户等级
msg.level=getusrlevel(msg.info.worknumber);
strcpy(msg.worknumber,msg.info.worknumber);
strcpy(event, "登录成功");
printf("登录成功\n");
// 登录成功发送1
msg.flags = 1;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
}
else
{
// 密码不对发送2
strcpy(event, "登录失败,密码不正确");
printf("密码不正确\n");
msg.flags = -3;
if (send(sfd, &msg, sizeof(msg), 0) < 0)
PRINT_ERR("send");
}
sqlite3_free_table(pres);
return 0;
}
// 判断用户是否在线,在线为1,反之为0
int User_isonline(char *name)
{
char sql[128];
sprintf(sql, "select flag from usr where worknumber='%s';", name);
char *errmsg = NULL;
char **pres;
int row, column;
if (sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
// 判断flag是否为1
if (strcmp(pres[1], "1") == 0)
{
sqlite3_free_table(pres);
return 1;
}
else
{
sqlite3_free_table(pres);
return 0;
}
}
// 用户上线,将flag置1
int User_online(char *worknumber)
{
char sql[128];
sprintf(sql, "UPDATE usr SET flag='1' WHERE worknumber='%s';", worknumber);
char *errmsg = NULL;
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
return 0;
}
// 用户下线,将flag置0
int User_logoff()
{
char sql[128];
sprintf(sql, "UPDATE usr SET flag='0' WHERE worknumber='%s';", msg.worknumber);
char *errmsg = NULL;
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
strcpy(event, "用户下线");
printf("工号:%s 退出登录!\n", msg.worknumber);
return 0;
}
// 添加用户
int Register(int sfd)
{
printf("工号:%s 密码:%s\n", msg.info.worknumber, msg.info.passwd);
char sql[256];
char *errmsg = NULL;
// 导入用户表,默认flag为0
sprintf(sql, "INSERT INTO usr VALUES (\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",%f,\"%s\");", msg.info.worknumber, msg.info.name, msg.info.passwd,
msg.info.age, msg.info.phone, msg.info.addr, msg.info.work, msg.info.date, msg.info.level, msg.info.salary, "0");
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("注册失败,已有该用户\n");
sprintf(event, "注册用户:%s 失败,已有该用户", msg.info.worknumber);
msg.flags = -2;
// 注册失败向客户端发送0
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
return -1;
}
printf("注册成功\n");
sprintf(event, "注册用户:%s 成功", msg.info.worknumber);
msg.flags = 1;
// 注册成功向客户端发送1
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
return 0;
}
// 删除用户
int Delete(int sfd)
{
printf("工号:%s\n", msg.info.worknumber);
if (IsuserExist(msg.info.worknumber) == 0)
{
msg.flags = -2;
printf("没有该用户\n");
sprintf(event, "删除用户:%s 失败,没有该用户", msg.info.worknumber);
// 没有该用户向客户端发送-1
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
return -1;
}
char sql[128];
char *errmsg = NULL;
// 导入用户表,默认flag为0
sprintf(sql, "delete from usr where worknumber='%s';", msg.info.worknumber);
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("删除失败\n");
sprintf(event, "删除用户:%s 失败", msg.info.worknumber);
msg.flags = -1;
// 删除失败失败向客户端发送0
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
return -1;
}
printf("删除成功\n");
sprintf(event, "删除用户:%s 成功", msg.info.worknumber);
msg.flags = 1;
// 删除成功向客户端发送1
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
return 0;
}
// 修改用户信息
int Update(int sfd)
{
printf("工号:%s\n", msg.info.worknumber);
if (IsuserExist(msg.info.worknumber) == 0)
{
msg.flags = -2;
printf("没有该用户\n");
sprintf(event, "修改用户:%s 的信息失败,没有该用户", msg.info.worknumber);
// 没有该用户向客户端发送-1
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
return -1;
}
char sql[512];
char *errmsg = NULL;
// 导入用户表,默认flag为0
sprintf(sql, "UPDATE usr SET '%s'='%s' WHERE worknumber='%s';", msg.recvmsg, msg.info.addr, msg.info.worknumber);
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("修改失败\n");
sprintf(event, "修改用户:%s 的信息失败", msg.info.worknumber);
msg.flags = -1;
// 修改失败向客户端发送0
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
return -1;
}
printf("修改成功\n");
sprintf(event, "将用户:%s的%s修改为%s", msg.info.worknumber, msg.recvmsg, msg.info.addr);
msg.flags = 1;
// 修改成功向客户端发送1
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
return 0;
}
// 查询用户信息
int Query(int sfd)
{
char sql[128];
if (msg.msgtype == 6)
{
printf("工号:%s\n", msg.info.worknumber);
if (IsuserExist(msg.info.worknumber) == 0)
{
// 没有该用户向客户端发送-2
msg.flags = -2;
printf("没有该用户\n");
sprintf(event, "查询用户:%s 的信息失败,没有该用户", msg.info.worknumber);
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
return -1;
}
sprintf(event, "查询用户:%s 的信息成功", msg.info.worknumber);
sprintf(sql, "select * from usr where worknumber='%s';", msg.info.worknumber);
}
else
{
sprintf(sql, "select * from usr;");
sprintf(event, "查询所有用户的信息成功");
}
char **pres;
char *errmsg = NULL;
int row, column;
if (sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
if (row == 0)
{ // 没有查询到发送-1
sprintf(event, "查询用户信息失败");
msg.flags = -1;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
return 0;
}
// 有数据发送1;
msg.flags = 1;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
for (int i = column; i + 1 < (row + 1) * column; i += 11)
{ // 循环发送
sprintf(msg.recvmsg, "║%-6s║%-10s║%-6s║%-6s║%-13s║%-6s║%-6s║%-10s║%-6s║%-10s║%-8s║\n", pres[i], pres[i + 1],
pres[i + 2], pres[i + 3], pres[i + 4], pres[i + 5], pres[i + 6], pres[i + 7], pres[i + 8], pres[i + 9], pres[i + 10]);
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
}
// 发送完,发送2表示发送完毕
msg.flags = 2;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
msg.flags = 0;
sqlite3_free_table(pres);
return 0;
}
// 将信息导入历史记录
int do_history(char *event)
{
char sql[256] = "";
char *errmsg = NULL;
char *times = gettime();
sprintf(sql, "INSERT INTO history VALUES ('%s','%s','%s');", gettime(), msg.worknumber, event);
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
return 0;
}
// 获取当前时间
char *gettime()
{
time_t ts;
struct tm *tm;
char *times = (char *)malloc(50);
ts = time(NULL);
tm = localtime(&ts);
sprintf(times, "%d-%02d-%02d %02d:%02d:%02d", tm->tm_year + 1900,
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
return times;
}
// 客户端查询日志信息
int select_history(int sfd)
{
char sql[128];
sprintf(sql, "select * from history;");
char **pres;
char *errmsg = NULL;
int row, column;
if (sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
if (row == 0)
{ // 没有查询到发送0
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
msg.flags = 0;
return 0;
}
//有数据发送1
msg.flags = 1;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
for (int i = column; i + 1 < (row + 1) * column; i += 3)
{
sprintf(msg.recvmsg, "║%-20s║%-5s║%-s\n", pres[i], pres[i + 1], pres[i + 2]);
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
}
// 发送完,再次发送2表示发送完毕
sprintf(event, "查看日志信息");
msg.flags = 2;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
sqlite3_free_table(pres);
return 0;
}
tcpcli_staff.c
#include <head.h>
#include "cliendhead.h"
staff_info_t info;
MSG msg;
int const size = sizeof(msg);
int sfd;
int main(int argc, const char *argv[])
{
// 初始化tcp客户端
sfd = init_tcpcli(IP, PORT);
// 捕获ctrl+c信号
signal(2, handler);
LD: // 登录页面
if (Login_page(sfd) == -1)
{ // 返回值为-1,说明用户选择退出
goto END;
}
int a;
// 先判断用户等级是否为管理员
if (msg.level == '0')
{ // 主页面
a = main_page_root(sfd);
}
else
{
a = main_page_ordinary(sfd);
}
if (a == -1)
{ // 返回值为-1,说明用户选择退出
goto END;
}
else if (a == 1)
{ // 返回值为1,说明用户选择返回,返回前先下线账号
end(sfd);
// 返回上一级退出当前账号,将用户名清空
bzero(&msg, size);
goto LD;
}
END:
handler(1);
return 0;
}
// 捕捉信号后的处理函数(退出函数)
void handler(int sig)
{
// 判断用户是否已登录,还未登录不用发送离线消息
if (strlen(msg.worknumber) != 0)
end(sfd);
close(sfd);
printf("\n谢谢使用\n");
exit(0);
}
// 初始化客户端
int init_tcpcli(char *ip, int port)
{
// 创建流式套接字
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd < 0)
PRINT_ERR("socket");
struct sockaddr_in sin_t;
sin_t.sin_family = AF_INET;
sin_t.sin_port = htons(port);
sin_t.sin_addr.s_addr = inet_addr(ip);
if (connect(sfd, (struct sockaddr *)&sin_t, sizeof(sin_t)) < 0)
PRINT_ERR("connect");
printf("成功连接服务器[%s:%d]\n", inet_ntoa(sin_t.sin_addr), ntohs(sin_t.sin_port));
return sfd;
}
// 登录页面
int Login_page(int sfd)
{
char c;
while (1)
{
system("clear");
printf("\033[2J\033[?25l"); // 清屏和隐藏光标
printf("\033[47m"); // 设置背景色
printf("\033[34m"); // 设置前景色
printf("\033[1m"); // 字体加粗
printf("\n");
printf("╔══════════════════════════════════════════╗\n");
printf("║ 员 工 管 理 系 统 ║\n");
printf("╟══════════════════════════════════════════╢\n");
printf("║ 1.登录 ║\n");
printf("║ ║\n");
printf("║ 2.退出 ║\n");
printf("║ ║\n");
printf("╚══════════════════════════════════════════╝\n");
printf("\033[0m"); // 恢复颜色
printf("\n");
printf("\033[31m"); // 设置前景色
printf("请输入>>>");
c = getchar();
while (getchar() != 10)
;
switch (c)
{
case '1':
c = Login(sfd);
break;
case '2':
return -1;
default:
printf("请输入正确的选项\n");
break;
}
if (c == 1)
{
printf("输入任意字符跳转>>>");
while (getchar() != 10)
;
break;
}
printf("输入任意字符清屏>>>");
while (getchar() != 10)
;
}
return c;
}
// 主页面(root用户)
int main_page_root(int sfd)
{
while (1)
{
system("clear");
printf("\033[47m"); // 设置背景色
printf("\033[34m"); // 设置前景色
printf("\033[1m"); // 字体加粗
printf("\n");
printf("╔══════════════════════════════════════════╗\n");
printf("║ 员 工 管 理 系 统 ║\n");
printf("╟══════════════════════════════════════════╢\n");
printf("║ 1.添加员工 2.删除员工 ║\n");
printf("║ 3.修改信息 4.查询个人信息 ║\n");
printf("║ 5.查询所有信息 6.查看日志 ║\n");
printf("║ 7.切换账号 8.退出系统 ║\n");
printf("╚══════════════════════════════════════════╝");
printf("\033[0m"); // 恢复颜色
printf("\n\n");
printf("\033[31m"); // 设置前景色
printf("请输入>>>");
char c = getchar();
while (getchar() != 10)
;
switch (c)
{
case '1':
Register(sfd);
break;
case '2':
Delete(sfd);
break;
case '3':;
Update(sfd);
break;
case '4':
msg.msgtype = 6;
Query(sfd);
break;
case '5':;
msg.msgtype = 7;
Query(sfd);
break;
case '6':
select_history(sfd);
break;
case '7':;
return 1;
break;
case '8':
return -1;
break;
default:
printf("请输入正确的选项\n");
break;
}
printf("输入任意字符清屏>>>");
while (getchar() != 10)
;
}
return 0;
}
// 主页面(普通用户)
int main_page_ordinary(int sfd)
{
while (1)
{
system("clear");
printf("\033[47m"); // 设置背景色
printf("\033[34m"); // 设置前景色
printf("\033[1m"); // 字体加粗
printf("\n");
printf("╔══════════════════════════════════════════╗\n");
printf("║ 员 工 管 理 系 统 ║\n");
printf("╟══════════════════════════════════════════╢\n");
printf("║ 1.修改信息 2.查询个人信息 ║\n");
printf("║ 3.切换账号 4.退出系统 ║\n");
printf("╚══════════════════════════════════════════╝");
printf("\033[0m"); // 恢复颜色
printf("\n\n");
printf("\033[31m"); // 设置前景色
printf("请输入>>>");
char c = getchar();
while (getchar() != 10)
;
switch (c)
{
case '1':;
Update(sfd);
break;
case '2':
msg.msgtype = 6;
Query(sfd);
break;
case '3':
return 1;
break;
case '4':
return -1;
break;
default:
printf("请输入正确的选项\n");
break;
}
printf("输入任意字符清屏>>>");
while (getchar() != 10)
;
}
return 0;
}
// 修改
int Update(int sfd)
{
if (msg.level == '0')
{
printf("请输入要修改的工人工号>>>");
scanf("%s", msg.info.worknumber);
getchar();
ANEW1:
system("clear");
printf("\033[47m"); // 设置背景色
printf("\033[34m"); // 设置前景色
printf("\033[1m"); // 字体加粗
printf("\n");
printf("╔══════════════════════════════════════════╗\n");
printf("║ 选项 ║\n");
printf("╟══════════════════════════════════════════╢\n");
printf("║ 1.员工编号 2.员工姓名 ║\n");
printf("║ 3.员工密码 4.员工年龄 ║\n");
printf("║ 5.员工电话 6.员工地址 ║\n");
printf("║ 7.员工职位 8.入职时间 ║\n");
printf("║ 9.员工等级 10.员工工资 ║\n");
printf("╚══════════════════════════════════════════╝");
printf("\033[0m"); // 恢复颜色
printf("\n\n");
printf("\033[31m"); // 设置前景色
printf("请输入>>>");
scanf("%d", &msg.flags);
getchar();
switch (msg.flags)
{
case 1:
strcpy(msg.recvmsg, "worknumber");
break;
case 2:
strcpy(msg.recvmsg, "name");
break;
case 3:
strcpy(msg.recvmsg, "password");
break;
case 4:
strcpy(msg.recvmsg, "age");
break;
case 5:
strcpy(msg.recvmsg, "phone");
break;
case 6:
strcpy(msg.recvmsg, "addr");
break;
case 7:
strcpy(msg.recvmsg, "work");
break;
case 8:
strcpy(msg.recvmsg, "time");
break;
case 9:
strcpy(msg.recvmsg, "lever");
break;
case 10:
strcpy(msg.recvmsg, "salary");
break;
default:
printf("请重新输入!\n");
printf("输入任意字符清屏>>>");
while (getchar() != 10)
;
goto ANEW1;
}
}
else
{
strcpy(msg.info.worknumber, msg.worknumber);
ANEW2:
system("clear");
printf("\033[47m"); // 设置背景色
printf("\033[34m"); // 设置前景色
printf("\033[1m"); // 字体加粗
printf("\n");
printf("╔══════════════════════════════════════════╗\n");
printf("║ 选项 ║\n");
printf("╟══════════════════════════════════════════╢\n");
printf("║ 1.员工姓名 2.员工密码 ║\n");
printf("║ 3.员工电话 4.员工地址 ║\n");
printf("╚══════════════════════════════════════════╝");
printf("\033[0m"); // 恢复颜色
printf("\n\n");
printf("\033[31m"); // 设置前景色
printf("请输入>>>");
scanf("%d", &msg.flags);
getchar();
switch (msg.flags)
{
case 1:
strcpy(msg.recvmsg, "name");
break;
case 2:
strcpy(msg.recvmsg, "password");
break;
case 3:
strcpy(msg.recvmsg, "phone");
break;
case 4:
strcpy(msg.recvmsg, "addr");
break;
default:
printf("请重新输入!\n");
printf("输入任意字符清屏>>>");
while (getchar() != 10)
;
goto ANEW2;
}
}
printf("请输入修改后的值>>>");
scanf("%s", msg.info.addr);
msg.msgtype = 4;
while (getchar() != 10)
;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
if (recv(sfd, &msg, size, 0) < 0)
PRINT_ERR("recv");
if (msg.flags == 1)
{
printf("修改成功\n");
return 1;
}
else if (msg.flags == -1)
printf("修改失败\n");
else if (msg.flags == -2)
printf("没有该用户\n");
return 0;
}
// 删除
int Delete(int sfd)
{
printf("请输入要删除的员工工号>>>");
scanf("%s", msg.info.worknumber);
msg.msgtype = 3;
while (getchar() != 10)
;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
if (recv(sfd, &msg, size, 0) < 0)
PRINT_ERR("recv");
if (msg.flags == 1)
{
printf("删除成功\n");
return 1;
}
else if (msg.flags == -1)
printf("删除失败\n");
else if (msg.flags == -2)
printf("没有该用户\n");
return 0;
}
// 查询
int Query(int sfd)
{
if (msg.level == '0')
{
if (msg.msgtype == 6)
{
printf("请输入要查询的员工工号>>>");
scanf("%s", msg.info.worknumber);
while (getchar() != 10)
;
}
}else
{
msg.msgtype == 6;
strcpy(msg.info.worknumber,msg.worknumber);
}
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
if (recv(sfd, &msg, size, 0) < 0)
PRINT_ERR("recv");
if (msg.flags == 1)
{
system("clear");
printf("查询成功\n");
printf("\033[47m"); // 设置背景色
printf("\033[34m"); // 设置前景色
printf("\033[1m"); // 字体加粗
printf("\n");
printf("╔═════════════════════════════════════════════════════════════════════════════════════════════════╗\n");
printf("║%-6s ║%-10s ║%-6s ║%-6s ║%-13s ║%-6s ║%-6s ║%-10s ║%-6s ║%-10s ║%-8s║\n", "工号", "密码", "姓名", "年龄", "手机号", "地址", "职位", "入职时间", "等级", "工资", "是否在线");
printf("╟═════════════════════════════════════════════════════════════════════════════════════════════════╢\n");
while (1)
{
if (recv(sfd, &msg, size, 0) < 0)
PRINT_ERR("recv");
if (msg.flags == 2)
break;
printf("%s", msg.recvmsg);
}
printf("╚═════════════════════════════════════════════════════════════════════════════════════════════════╝");
printf("\033[0m"); // 恢复颜色
printf("\n\n");
printf("\033[31m"); // 设置前景色
return 1;
}
else if (msg.flags == -1)
printf("查询失败\n");
else if (msg.flags == -2)
printf("没有该用户\n");
return 0;
}
// 查看日志
int select_history(int sfd)
{
msg.msgtype = 8;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
if (recv(sfd, &msg, size, 0) < 0)
PRINT_ERR("recv");
if (msg.flags == 1)
{
system("clear");
printf("查询成功\n");
printf("╔══════════════════════════════════════════════════\n");
printf("║%-22s║%-7s║%-38s\n", "时间", "用户", "事件");
printf("╟══════════════════════════════════════════════════\n");
while (1)
{
if (recv(sfd, &msg, size, 0) < 0)
PRINT_ERR("recv");
if (msg.flags == 2)
break;
printf("%s", msg.recvmsg);
}
printf("╚══════════════════════════════════════════════════");
printf("\n");
return 1;
}
else if (msg.flags == -1)
printf("查询失败\n");
return 0;
}
// 登录
int Login(int sfd)
{
printf("(账号和密码用空格隔开)\n");
printf("请输入账号和密码>>>");
scanf("%s %s", msg.info.worknumber, msg.info.passwd);
while (getchar() != 10)
;
msg.msgtype = 2;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
if (recv(sfd, &msg, size, 0) < 0)
PRINT_ERR("recv");
if (msg.flags == 1)
{
printf("登录成功\n");
// 登录成功将次客户端与工号绑定
strcpy(msg.worknumber, msg.info.worknumber);
return 1;
}
else if (msg.flags == -2)
printf("不存在该用户\n");
else if (msg.flags == -3)
printf("密码不正确\n");
else if (msg.flags == -4)
printf("账号已在别处登录\n");
return 0;
}
// 注册
int Register(int sfd)
{
printf("请输入要注册的员工编号、姓名、密码、年龄、电话、地址、职位、入职时间、等级、工资 \n");
scanf("%s %s %s %s %s %s %s %s %s %lf", msg.info.worknumber, msg.info.name, msg.info.passwd,
msg.info.age, msg.info.phone, msg.info.addr, msg.info.work, msg.info.date, msg.info.level, &msg.info.salary);
msg.msgtype = 1;
while (getchar() != 10)
;
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
if (recv(sfd, &msg, size, 0) < 0)
PRINT_ERR("recv");
if (msg.flags == 1)
printf("注册成功\n");
else
printf("注册失败,已存在该用户\n");
return 0;
}
// 下线
int end(int sfd)
{
msg.msgtype = 5;
// 封装数据包,5代表该用户下线
if (send(sfd, &msg, size, 0) < 0)
PRINT_ERR("send");
printf("\033[0m"); // 恢复颜色
return 0;
}