项目名称:员工管理系统
项目时间:3天
项目描述:
1)服务器负责管理所有员工表单(以数据库形式或文件形式都可),其他客户端可通过网络连接服务器来查询员工表单。
2)需要账号密码登陆,其中需要区分管理员账号还是普通用户账号。
3)管理员账号可以查看、修改员工表单,管理员要负责管理所有的普通用户。
4)普通用户只能查询修改与本人有关的相关信息,其他员工信息(出于保密原则)不得泄露。
5)有查询历史记录功能。
6)能同时处理多台客户端的请求功能。
【1】TCP通信的编程步骤 1.服务器: 1)创建套接字 2)绑定ip和端口号 3)监听 4)等待客户端连接 int main() { //1.创建套接字 int sockfd = socket(); //2.初始化通信结构 struct sockaddr_in addr; addr.sin_family=AF_INET; addr.sin_port = port; addr.sin_addr=addr; bind(sockfd, &addr); //3.监听 listen(); //4.连接 while(1) { int connfd = accept(); //5.循环数据收发 while(1) { recv(); send(); } } close(sockfd); close(connfd); } 2.客户端: 1)创建套接字 2)连接服务器 int main() { //1.创建套接字 int sockfd = socket(); //2.初始化通信结构 struct sockaddr_in addr; addr.sin_family=AF_INET; addr.sin_port = port; addr.sin_addr=addr; //3.连接 connect(); //5.循环数据收发 while(1) { send(); recv(); } } 【2】服务器模型 1.循环服务器 2.并发服务器 1)多线程 2)多进程 3)IO多路复用: a. select: 基本思想: 1. 先构造一张有关文件描述符的表(集合、数组); fd_set fd; 2. 将你关心的文件描述符加入到这个表中;FD_SET(); 3. 然后调用一个函数。 select / poll 4. 当这些文件描述符中的一个或多个已准备好进行I/O操作的时候 该函数才返回(阻塞)。 5. 判断是哪一个或哪些文件描述符产生了事件(IO操作); 6. 做对应的逻辑处理; ****select函数返回之后,会自动将除了产生事件的文件描述符以外的位全部清空; 程序步骤: 1.把关心的文件描述符放入集合--FD_SET 2.监听集合中的文件描述符--select 3.依次判断哪个文件描述符有数据--FD_ISSET 4.依次处理有数据的文件描述符的数据 伪代码: fd_set fd; FD_SET(sockfd); while(1) { 设置监听读写文件描述符集合(FD_*); 调用select; select(); 如果是监听套接字就绪,说明有新的连接请求 if(sockfd) { 建立连接(); int connfd = accept(); 加入到监听文件描述符集合; FD_SET(connfd); }否则说明是一个已经连接过的描述符 else { 进行操作(send或者recv); recv(); send(); } } select弊端: 1. 一个进程最多只能监听1024个文件描述符 (千级别) 2. select是一种轮询的机制; 3. 涉及到用户态和内核态的数据拷贝; b. poll 1. 优化文件描述符个数的限制; 2. poll是一种轮询的机制; 3. 涉及到用户态和内核态的数据拷贝; 函数接口: int poll(struct pollfd *fds, nfds_t nfds, int timeout); 参数: struct pollfd *fds 关心的文件描述符数组struct pollfd fds[N]; nfds:个数 timeout: 超市检测 毫秒级的:如果填1000,1秒 如果-1,阻塞 问题: 我想检测是键盘事件(标准输入 文件描述如为0 ), 还是鼠标事件(文件描述符是/dev/input/mouse1); 1. 创建一个结构体数组 struct pollfd fds[2]; 2. 将你关心的文件描述符加入到结构体成员中 struct pollfd { int fd; // 关心的文件描述符; short events; // 关心的事件,读 short revents; // 如果产生事件,则会自动填充该成员的值 }; // 键盘 fds[0].fd = 0; fds[0].events = POLLIN; //鼠标 fds[1].fd = mouse1_fd; fds[1].events = POLLIN; 3. 调用poll函数 如果返回表示有事件产生; poll(fds,2,1000) 4. 判断具体是哪个文件描述符产生了事件 if(fds[0].revents == POLLIN) { .... } c. epoll 1. 没有文件描述符的限制 2. 异步IO,当有事件产生,文件描述符主动调用callback 3. 不用数据拷贝; 3个功能函数: #include
int epoll_create(int size);//创建红黑树根节点 //成功时返回epoll文件描述符,失败时返回-1 //控制epoll属性 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); epfd:epoll_create函数的返回句柄。 op:表示动作类型。有三个宏 来表示: EPOLL_CTL_ADD:注册新的fd到epfd中 EPOLL_CTL_MOD:修改已注册fd的监听事件 EPOLL_CTL_DEL:从epfd中删除一个fd FD:需要监听的fd。 event:告诉内核需要监听什么事件 EPOLLIN:表示对应文件描述符可读 EPOLLOUT:可写 EPOLLPRI:有紧急数据可读; EPOLLERR:错误; EPOLLHUP:被挂断; EPOLLET:触发方式,电平触发; ET模式:表示状态的变化; //成功时返回0,失败时返回-1 //等待事件到来 int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); 功能:等待事件的产生,类似于select嗲用 epfd:句柄; events:用来从内核得到事件的集合; maxevents:表示每次能处理事件最大个数; timeout:超时时间,毫秒,0立即返回,-1阻塞 //成功时返回发生事件的文件描述数,失败时返回-1 伪代码: 1.定义epoll事件,创建epoll的fd int epfd,epct,i; struct epoll_event event; //定义epoll 事件 struct epoll_event events[20]; //定义epoll 事件集合 epfd = epoll_create(1); // 创建epoll 的fd 2.填充事件 event.data.fd = serverFd; //填充事件的fd event.events = EPOLLIN | EPOLLET; //填充 事件类型 epoll_ctl(epfd,EPOLL_CTL_ADD,serverFd,&event); //把serverFd(监听FD)注册到epfd中 3.监听事件 while(1){ epct = epoll_wait(epfd,events,20,-1); // 等待事件到来,阻塞模式 for(i=0;i
#ifndef _COMMON_H_
#define _COMMON_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define STAFF_DATABASE "staff_manage_system.db"
#define USER_LOGIN 0x00000000 // login 登陆 0x00000001
#define USER_MODIFY 0x00000001 // user-modification 修改
#define USER_QUERY 0x00000002 // user-query 查询
#define ADMIN_LOGIN 0x10000000 // login 登陆 0x00000001
#define ADMIN_MODIFY 0x10000001 // admin_modification 修改
#define ADMIN_ADDUSER 0x10000002 // admin_adduser 添加
#define ADMIN_DELUSER 0x10000004 // admin_deluser 删除
#define ADMIN_QUERY 0x10000008 //hitory_query 查找
#define ADMIN_HISTORY 0x10000010 //hitory_history 历史
#define ADMIN_LIST 0x10000011 //列表
#define QUIT 0x11111111
#define ADMIN 0 //管理员
#define USER 1 //用户
#define PASSLEN 8
#define NAMELEN 16
#define DATALEN 128
/*员工基本信息*/
typedef struct staff_info
{
int no; //员工编号
int usertype; //ADMIN 1 USER 2
char name[NAMELEN]; //姓名
char passwd[PASSLEN]; //密码
int age; // 年龄
char phone[NAMELEN]; //电话
char addr[DATALEN]; // 地址
char work[DATALEN]; //职位
char date[DATALEN]; //入职年月
int level; // 等级
int salary; // 工资
}staff_info_t;
/*定义双方通信的结构体信息*/
typedef struct
{
int msgtype; //请求的消息类型
int usertype; //ADMIN 1 USER 2
char username[NAMELEN]; //姓名
char passwd[PASSLEN]; //登陆密码
char recvmsg[DATALEN]; //通信的消息
int flags; //标志位
staff_info_t info; //员工信息
}MSG;
#define S_IP "10.0.12.9"
#define IP "124.223.177.144"
#define PORT "8888"
char user_name[NAMELEN]; //姓名
char user_passwd[PASSLEN]; //登陆密码
char history[DATALEN+100];
#endif
int process_user_or_admin_login_request(int acceptfd, MSG *msg);
int process_user_modify_request(int acceptfd, MSG *msg);
int process_user_query_request(int acceptfd, MSG *msg);
int process_admin_modify_request(int acceptfd, MSG *msg);
int process_admin_adduser_request(int acceptfd, MSG *msg);
int process_admin_deluser_request(int acceptfd, MSG *msg);
int process_admin_query_request(int acceptfd, MSG *msg);
int process_admin_history_request(int acceptfd, MSG *msg);
int process_admin_list_request(int acceptfd, MSG *msg);
int process_client_quit_request(int acceptfd, MSG *msg);
int process_client_request(int acceptfd, MSG *msg);
int process_recv_history_request(char *name,char *str);
#include "common.h"
#include "server.h"
sqlite3 *db = NULL;
//登录
int process_user_or_admin_login_request(int acceptfd, MSG *msg)
{
//封装sql命令,表中查询用户名和密码-存在-登录成功-发送响应-失败-发送失败响应
char sql[DATALEN] = {0};
char *errmsg;
char **result;
int nrow, ncolumn;
msg->info.usertype = msg->usertype;
strcpy(msg->info.name, msg->username);
strcpy(msg->info.passwd, msg->passwd);
strcpy(user_name, msg->username);
strcpy(user_passwd, msg->username);
printf("usertype: %#x ,username: %s ,userpasswd: %s.\n", msg->info.usertype, msg->info.name, msg->info.passwd);
sprintf(sql, "select * from usrinfo where usertype=%d and name='%s' and passwd='%s';", msg->info.usertype, msg->info.name, msg->info.passwd);
if (sqlite3_get_table(db, sql, &result, &nrow, &ncolumn, &errmsg) != SQLITE_OK)
{
printf("---****----%s.\n", errmsg);
}
else
{
// printf("----nrow-----%d,ncolumn-----%d.\n",nrow,ncolumn);
if (nrow == 0)
{
//查询到行为0
strcpy(msg->recvmsg, "name or passwd failed.\n");
send(acceptfd, msg, sizeof(MSG), 0);
process_recv_history_request(msg->username, "longin error!");
}
else
{
strcpy(msg->recvmsg, "OK");
send(acceptfd, msg, sizeof(MSG), 0);
process_recv_history_request(msg->username, "longin success!");
}
}
return 0;
}
//用户修改
int process_user_modify_request(int acceptfd, MSG *msg)
{
char cmd[NAMELEN] = "";
char *errmsg;
char sql[DATALEN + 100] = "";
int nrow = 0, ncolumn;
char **result;
switch (msg->flags)
{
case 1:
sprintf(sql, "select * from usrinfo where taffon=%d;",msg->info.no);
if (sqlite3_get_table(db, sql, &result, &nrow, &ncolumn, &errmsg) == SQLITE_OK)
{
memset(msg->recvmsg, 0, DATALEN);
strcpy(msg->recvmsg, "no");
send(acceptfd, msg, sizeof(MSG), 0);
sqlite3_free_table(result);
return -1;
}
sprintf(sql, "UPDATE usrinfo SET taffon=%d WHERE name='%s' AND passwd='%s';", msg->info.no, msg->username, msg->passwd);
memset(history, 0, DATALEN);
sprintf(history,"change taffon -> %d", msg->info.no);
process_recv_history_request(msg->username, history);
break;
case 2:
// sprintf(sql, "UPDATE usrinfo SET usertype=%d WHERE name='%s' AND passwd='%s';",msg->info.usertype,msg->username,msg->passwd);
{
memset(msg, 0, sizeof(MSG));
strcpy(msg->recvmsg, "no");
if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the client error\n");
return -1;
}
return -1;
}
break;
case 3:
sprintf(sql, "UPDATE usrinfo SET name='%s' WHERE name='%s' AND passwd='%s';", msg->info.name, msg->username, msg->passwd);
memset(history, 0, DATALEN);
sprintf(history,"change name -> %s", msg->info.name);
process_recv_history_request(msg->username, history);
break;
case 4:
sprintf(sql, "UPDATE usrinfo SET passwd='%s' WHERE name='%s' AND passwd='%s';", msg->info.passwd, msg->username, msg->passwd);
memset(history, 0, DATALEN);
sprintf(history,"change passwd -> %s", msg->info.passwd);
process_recv_history_request(msg->username, history);
break;
case 5:
sprintf(sql, "UPDATE usrinfo SET age=%d WHERE name='%s' AND passwd='%s';", msg->info.age, msg->username, msg->passwd);
memset(history, 0, DATALEN);
sprintf(history,"change age -> %d", msg->info.age);
process_recv_history_request(msg->username, history);
break;
case 6:
sprintf(sql, "UPDATE usrinfo SET phone='%s' WHERE name='%s' AND passwd='%s';", msg->info.phone, msg->username, msg->passwd);
memset(history, 0, DATALEN);
sprintf(history,"change phone -> %s", msg->info.phone);
process_recv_history_request(msg->username, history);
break;
case 7:
sprintf(sql, "UPDATE usrinfo SET addr='%s' WHERE name='%s' AND passwd='%s';", msg->info.addr, msg->username, msg->passwd);
memset(history, 0, DATALEN);
sprintf(history,"change addr -> %s", msg->info.addr);
process_recv_history_request(msg->username, history);
break;
case 8:
sprintf(sql, "UPDATE usrinfo SET work='%s' WHERE name='%s' AND passwd='%s';", msg->info.work, msg->username, msg->passwd);
memset(history, 0, DATALEN);
sprintf(history,"change work -> %s", msg->info.work);
process_recv_history_request(msg->username, history);
break;
case 9:
sprintf(sql, "UPDATE usrinfo SET date='%s' WHERE name='%s' AND passwd='%s';", msg->info.date, msg->username, msg->passwd);
memset(history, 0, DATALEN);
sprintf(history,"change date -> %s", msg->info.date);
process_recv_history_request(msg->username, history);
break;
case 10:
sprintf(sql, "UPDATE usrinfo SET level=%d WHERE name='%s' AND passwd='%s';", msg->info.level, msg->username, msg->passwd);
memset(history, 0, DATALEN);
sprintf(history,"change level -> %d", msg->info.level);
process_recv_history_request(msg->username, history);
break;
case 11:
sprintf(sql, "UPDATE usrinfo SET salary=%d WHERE name='%s' AND passwd='%s';", msg->info.salary, msg->username, msg->passwd);
memset(history, 0, DATALEN);
sprintf(history,"change salary -> %d", msg->info.salary);
process_recv_history_request(msg->username, history);
break;
default:
printf("enter error\n");
return -1;
}
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
memset(msg, 0, sizeof(MSG));
strcpy(msg->recvmsg, "no");
if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the client error\n");
return -1;
}
return -1;
}
memset(msg, 0, sizeof(MSG));
strcpy(msg->recvmsg, "ok");
if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the client error\n");
return -1;
}
return 1;
}
//用户查找
int process_user_query_request(int acceptfd, MSG *msg)
{
char sql[DATALEN + 50] = "";
char **result = NULL;
int row, column;
char *errmsg = NULL;
memset(history, 0, DATALEN);
sprintf(history,"query self request");
process_recv_history_request(msg->username, history);
sprintf(sql, "select * from usrinfo where name='%s' and passwd='%s';", msg->username, msg->passwd);
if (sqlite3_get_table(db, sql, &result, &row, &column, &errmsg) != SQLITE_OK)
{
goto end;
}
printf("查询结果成功\n");
if (row == 0)
{
memset(msg->recvmsg, 0, DATALEN);
strcpy(msg->recvmsg, "no");
send(acceptfd, msg, sizeof(MSG), 0);
sqlite3_free_table(result);
return -1;
}
printf("row=%d column=%d\n", row, column);
int i = 0;
memset(msg->recvmsg, 0, DATALEN);
for (i = 11; i < (row + 1) * column; i++)
{
switch (i % column)
{
case 0:
msg->info.no = atoi(result[i]);
break;
case 1:
msg->info.usertype = atoi(result[i]);
break;
case 2:
strcpy(msg->info.name, result[i]);
break;
case 3:
strcpy(msg->info.passwd, result[i]);
break;
case 4:
msg->info.age = atoi(result[i]);
break;
case 5:
strcpy(msg->info.phone, result[i]);
break;
case 6:
strcpy(msg->info.addr, result[i]);
break;
case 7:
strcpy(msg->info.work, result[i]);
break;
case 8:
strcpy(msg->info.date, result[i]);
break;
case 9:
msg->info.level = atoi(result[i]);
break;
case 10:
msg->info.salary = atoi(result[i]);
break;
default:
break;
}
if (i % column == (column - 1))
{
send(acceptfd, msg, sizeof(MSG), 0);
memset(msg->recvmsg, 0, DATALEN);
}
}
putchar(10);
end:
memset(msg->recvmsg, 0, DATALEN);
strcpy(msg->recvmsg, "end");
send(acceptfd, msg, sizeof(MSG), 0);
//释放查询到的结果
sqlite3_free_table(result);
return 0;
}
//管理修改
int process_admin_modify_request(int acceptfd, MSG *msg)
{
char cmd[NAMELEN] = "";
char *errmsg;
char sql[DATALEN + 100] = "";
int nrow = 0, ncolumn;
char **result;
sprintf(sql, "select * from usrinfo where name='%s';", msg->username);
if (sqlite3_get_table(db, sql, &result, &nrow, &ncolumn, &errmsg) != SQLITE_OK)
{
printf("---select error----%s.\n", errmsg);
}
if (nrow == 0)
{
//如果此人信息不存在
memset(msg, 0, sizeof(MSG));
strcpy(msg->recvmsg, "no");
send(acceptfd, msg, sizeof(MSG), 0);
return 0;
}
switch (msg->flags)
{
case 1:
sprintf(sql, "UPDATE usrinfo SET taffon=%d WHERE name='%s';", msg->info.no, msg->username);
memset(history, 0, DATALEN);
sprintf(history,"change %s taffon -> %d",msg->username,msg->info.no);
process_recv_history_request(msg->username, history);
break;
case 2:
sprintf(sql, "UPDATE usrinfo SET usertype=%d WHERE name='%s';", msg->info.usertype, msg->username);
memset(history, 0, DATALEN);
sprintf(history,"change %s usertype -> %s",msg->username, msg->info.name);
process_recv_history_request(msg->username, history);
break;
case 3:
sprintf(sql, "UPDATE usrinfo SET name='%s' WHERE name='%s';", msg->info.name, msg->username);
memset(history, 0, DATALEN);
sprintf(history,"change %s name -> %s",msg->username, msg->info.name);
process_recv_history_request(msg->username, history);
break;
case 4:
sprintf(sql, "UPDATE usrinfo SET passwd='%s' WHERE name='%s';", msg->info.passwd, msg->username);
memset(history, 0, DATALEN);
sprintf(history,"change %s passwd -> %s",msg->username, msg->info.passwd);
process_recv_history_request(msg->username, history);
break;
case 5:
sprintf(sql, "UPDATE usrinfo SET age=%d WHERE name='%s';", msg->info.age, msg->username);
memset(history, 0, DATALEN);
sprintf(history,"change %s age -> %d", msg->username,msg->info.age);
process_recv_history_request(msg->username, history);
break;
case 6:
sprintf(sql, "UPDATE usrinfo SET phone='%s' WHERE name='%s';", msg->info.phone, msg->username);
memset(history, 0, DATALEN);
sprintf(history,"change %s phone -> %s",msg->username, msg->info.phone);
process_recv_history_request(msg->username, history);
break;
case 7:
sprintf(sql, "UPDATE usrinfo SET addr='%s' WHERE name='%s';", msg->info.addr, msg->username);
memset(history, 0, DATALEN);
sprintf(history,"change %s addr -> %s",msg->username, msg->info.addr);
process_recv_history_request(msg->username, history);
break;
case 8:
sprintf(sql, "UPDATE usrinfo SET work='%s' WHERE name='%s';", msg->info.work, msg->username);
memset(history, 0, DATALEN);
sprintf(history,"change %s work -> %s",msg->username, msg->info.work);
process_recv_history_request(msg->username, history);
break;
case 9:
sprintf(sql, "UPDATE usrinfo SET date='%s' WHERE name='%s';", msg->info.date, msg->username);
memset(history, 0, DATALEN);
sprintf(history,"change %s date -> %s",msg->username, msg->info.date);
process_recv_history_request(msg->username, history);
break;
case 10:
sprintf(sql, "UPDATE usrinfo SET level=%d WHERE name='%s';", msg->info.level, msg->username);
memset(history, 0, DATALEN);
sprintf(history,"change %s level -> %d",msg->username, msg->info.level);
process_recv_history_request(msg->username, history);
break;
case 11:
sprintf(sql, "UPDATE usrinfo SET salary=%d WHERE name='%s';", msg->info.salary, msg->username);
memset(history, 0, DATALEN);
sprintf(history,"change %s salary -> %d", msg->username,msg->info.salary);
process_recv_history_request(msg->username, history);
break;
default:
printf("enter error\n");
return -1;
}
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
memset(msg, 0, sizeof(MSG));
strcpy(msg->recvmsg, "ok");
if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the client error\n");
return -1;
}
return 1;
}
//管理添加
int process_admin_adduser_request(int acceptfd, MSG *msg)
{
char cmd[NAMELEN] = "";
char *errmsg;
char sql[DATALEN + 400] = "";
int nrow = 0, ncolumn;
char **result;
memset(history, 0, DATALEN);
sprintf(history,"%s add %s",user_name,msg->info.name);
process_recv_history_request(msg->username, history);
sprintf(sql, "select * from usrinfo where staffno=%d;", msg->info.no);
if (sqlite3_get_table(db, sql, &result, &nrow, &ncolumn, &errmsg) != SQLITE_OK)
{
printf("%d\n", __LINE__);
memset(msg, 0, sizeof(MSG));
strcpy(msg->recvmsg, "no");
send(acceptfd, msg, sizeof(MSG), 0);
return -1;
}
if (nrow != 0)
{
//如果此人信息存在
printf("%d\n", __LINE__);
memset(msg, 0, sizeof(MSG));
strcpy(msg->recvmsg, "no");
send(acceptfd, msg, sizeof(MSG), 0);
return 0;
}
sprintf(sql, "INSERT INTO usrinfo VALUES (%d,%d,'%s','%s',%d,'%s','%s','%s','%s',%d,%d);", msg->info.no, msg->info.usertype, 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);
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
memset(msg, 0, sizeof(MSG));
strcpy(msg->recvmsg, "ok");
if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the client error\n");
return -1;
}
}
//管理删除
int process_admin_deluser_request(int acceptfd, MSG *msg)
{
char sql[DATALEN] = "";
char *errmsg;
memset(history, 0, DATALEN);
sprintf(history,"%s del no -> %d",user_name,msg->info.no);
process_recv_history_request(msg->username, history);
sprintf(sql, "DELETE FROM usrinfo WHERE staffno=%d;", msg->info.no);
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
memset(msg, 0, sizeof(MSG));
strcpy(msg->recvmsg, "no");
if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the client error\n");
return -1;
}
return -1;
}
memset(msg, 0, sizeof(MSG));
strcpy(msg->recvmsg, "ok");
if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the client error\n");
return -1;
}
}
//管理查找
int process_admin_query_request(int acceptfd, MSG *msg)
{
char sql[DATALEN + 50] = "";
char **result = NULL;
int row, column;
char *errmsg = NULL;
memset(history, 0, DATALEN);
sprintf(history,"find no-> %d",msg->info.no);
process_recv_history_request(user_name, history);
sprintf(sql, "select * from usrinfo where staffno=%d;", atoi(msg->recvmsg));
if (sqlite3_get_table(db, sql, &result, &row, &column, &errmsg) != SQLITE_OK)
{
goto end;
}
printf("查询结果成功\n");
if (row == 0)
{
memset(msg->recvmsg, 0, DATALEN);
strcpy(msg->recvmsg, "no");
send(acceptfd, msg, sizeof(MSG), 0);
sqlite3_free_table(result);
return -1;
}
printf("row=%d column=%d\n", row, column);
int i = 0;
memset(msg->recvmsg, 0, DATALEN);
for (i = 11; i < (row + 1) * column; i++)
{
switch (i % column)
{
case 0:
msg->info.no = atoi(result[i]);
break;
case 1:
msg->info.usertype = atoi(result[i]);
break;
case 2:
strcpy(msg->info.name, result[i]);
break;
case 3:
strcpy(msg->info.passwd, result[i]);
break;
case 4:
msg->info.age = atoi(result[i]);
break;
case 5:
strcpy(msg->info.phone, result[i]);
break;
case 6:
strcpy(msg->info.addr, result[i]);
break;
case 7:
strcpy(msg->info.work, result[i]);
break;
case 8:
strcpy(msg->info.date, result[i]);
break;
case 9:
msg->info.level = atoi(result[i]);
break;
case 10:
msg->info.salary = atoi(result[i]);
break;
default:
break;
}
if (i % column == (column - 1))
{
send(acceptfd, msg, sizeof(MSG), 0);
memset(msg->recvmsg, 0, DATALEN);
}
}
putchar(10);
end:
memset(msg->recvmsg, 0, DATALEN);
strcpy(msg->recvmsg, "end");
send(acceptfd, msg, sizeof(MSG), 0);
//释放查询到的结果
sqlite3_free_table(result);
return 0;
}
//管理历史
int process_admin_history_request(int acceptfd, MSG *msg)
{
memset(history, 0, DATALEN);
sprintf(history,"(passwd:%s) -> cat history",user_passwd);
process_recv_history_request(user_name, history);
char sql[DATALEN] = "";
char **result = NULL;
int row, column;
char *errmsg = NULL;
sprintf(sql, "SELECT * FROM historyinfo;");
if (sqlite3_get_table(db, sql, &result, &row, &column, &errmsg) != SQLITE_OK)
{
memset(msg->recvmsg, 0, DATALEN);
msg->flags = 1;
send(acceptfd, msg, sizeof(MSG), 0);
//释放查询到的结果
sqlite3_free_table(result);
return -1;
}
printf("查询结果成功\n");
if (row == 0)
{
memset(msg->recvmsg, 0, DATALEN);
//strcpy(msg->recvmsg, "no");
msg->flags = 2;
send(acceptfd, msg, sizeof(MSG), 0);
sqlite3_free_table(result);
return -1;
}
printf("row=%d column=%d\n", row, column);
int i = 0;
for (i = 3; i < (row + 1) * column; i++)
{
strcat(msg->recvmsg, result[i]);
strcat(msg->recvmsg, "\t");
if (i % column == (column - 1))
{
strcat(msg->recvmsg, "\n");
send(acceptfd, msg, sizeof(MSG), 0);
recv(acceptfd, msg, sizeof(MSG), 0);
printf("%s",msg->recvmsg);
memset(msg->recvmsg, 0, DATALEN);
}
}
memset(msg->recvmsg, 0, DATALEN);
msg->flags = 1;
send(acceptfd, msg, sizeof(MSG), 0);
//释放查询到的结果
sqlite3_free_table(result);
}
int process_recv_history_request(char *name, char *str)
{
char data[11] = ""; // 2022/10/29
char timeb[9] = ""; // 02:18:00
char his[50] = "";
char sql[DATALEN] = "";
char *errmsg = NULL;
strcat(his, name);
strcat(his, " : ");
strcat(his, str);
//转换成日历格式
struct tm *p = NULL;
long int q;
q = time(NULL);
p = localtime(&q);
sprintf(data, "%04d-%02d-%02d", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday);
sprintf(timeb, "%02d:%02d:%02d", p->tm_hour, p->tm_min, p->tm_sec);
sprintf(sql, "INSERT INTO historyinfo VALUES ('%s','%s','%s');", data, timeb, his);
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
}
//列表
int process_admin_list_request(int acceptfd, MSG *msg)
{
memset(history, 0, DATALEN);
sprintf(history,"(passwd:%s) -> cat list",user_passwd);
process_recv_history_request(user_name, history);
char sql[DATALEN] = "";
char **result = NULL;
int row, column;
char *errmsg = NULL;
sprintf(sql, "SELECT * FROM usrinfo;");
if (sqlite3_get_table(db, sql, &result, &row, &column, &errmsg) != SQLITE_OK)
{
goto end;
}
printf("查询结果成功\n");
if (row == 0)
{
memset(msg->recvmsg, 0, DATALEN);
strcpy(msg->recvmsg, "no");
send(acceptfd, msg, sizeof(MSG), 0);
sqlite3_free_table(result);
return -1;
}
printf("row=%d column=%d\n", row, column);
int i = 0;
memset(msg->recvmsg, 0, DATALEN);
for (i = 11; i < (row + 1) * column; i++)
{
switch (i % column)
{
case 0:
msg->info.no = atoi(result[i]);
break;
case 1:
msg->info.usertype = atoi(result[i]);
break;
case 2:
strcpy(msg->info.name, result[i]);
break;
case 3:
strcpy(msg->info.passwd, result[i]);
break;
case 4:
msg->info.age = atoi(result[i]);
break;
case 5:
strcpy(msg->info.phone, result[i]);
break;
case 6:
strcpy(msg->info.addr, result[i]);
break;
case 7:
strcpy(msg->info.work, result[i]);
break;
case 8:
strcpy(msg->info.date, result[i]);
break;
case 9:
msg->info.level = atoi(result[i]);
break;
case 10:
msg->info.salary = atoi(result[i]);
break;
default:
break;
}
if (i % column == (column - 1))
{
send(acceptfd, msg, sizeof(MSG), 0);
recv(acceptfd, msg, sizeof(MSG), 0);
memset(msg->recvmsg, 0, DATALEN);
}
}
putchar(10);
end:
memset(msg->recvmsg, 0, DATALEN);
strcpy(msg->recvmsg, "endd");
send(acceptfd, msg, sizeof(MSG), 0);
//释放查询到的结果
sqlite3_free_table(result);
}
//客户端退出
int process_client_quit_request(int acceptfd, MSG *msg)
{
printf("------------%s-----------%d.\n", __func__, __LINE__);
}
//处理客户端请求
int process_client_request(int acceptfd, MSG *msg)
{
//请求的消息类型
switch (msg->msgtype)
{
case USER_LOGIN:
case ADMIN_LOGIN:
process_user_or_admin_login_request(acceptfd, msg); //登录
break;
case USER_MODIFY:
process_user_modify_request(acceptfd, msg); //用户修改
break;
case USER_QUERY:
process_user_query_request(acceptfd, msg); //用户查找
break;
case ADMIN_MODIFY:
process_admin_modify_request(acceptfd, msg); //管理修改
break;
case ADMIN_ADDUSER:
process_admin_adduser_request(acceptfd, msg); //管理添加
break;
case ADMIN_DELUSER:
process_admin_deluser_request(acceptfd, msg); //管理删除
break;
case ADMIN_QUERY:
process_admin_query_request(acceptfd, msg); //管理查找
break;
case ADMIN_HISTORY:
process_admin_history_request(acceptfd, msg); //管理历史
break;
case ADMIN_LIST:
process_admin_list_request(acceptfd, msg); //列表
break;
case QUIT:
process_client_quit_request(acceptfd, msg); //客户端退出
break;
default:
break;
}
}
int main(int argc, const char *argv[])
{
system("clear");
//打开数据库
if (sqlite3_open(STAFF_DATABASE, &db) != SQLITE_OK)
{
printf("%s.\n", sqlite3_errmsg(db));
return -1;
}
printf("database open success\n");
// socket->填充->绑定->监听->等待连接->数据交互->关闭
//创建网络通信的套接字
int socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd < 0)
{
printf("socket error\n");
return -1;
}
printf("socket success\n");
//允许端口快速重用
int reuse = 1;
if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
printf("setsockopt error\n");
return -1;
}
printf("setsockopt success\n");
//填充网络结构体
//填充服务器网路信息结构体
struct sockaddr_in sin;
//填充为IPV4地址
sin.sin_family = AF_INET;
//填充服务器IP
sin.sin_addr.s_addr = inet_addr(S_IP);
//填充服务器端口号
sin.sin_port = htons(atoi(PORT));
//绑定网络套接字和网络结构体
if (bind(socketfd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
printf("bind error\n");
return -1;
}
printf("bind success\n");
//监听套接字,将主动套接字转化为被动套接字
if (listen(socketfd, 10) < 0)
{
printf("listen error\n");
return -1;
}
printf("listen success\n");
//通过select实现并发
//客户端网络信息结构体
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
//创建一个读集合
fd_set readfds, tempfds;
//将集合清空
FD_ZERO(&readfds);
FD_ZERO(&tempfds);
//将sfd文件描述符添加到集合
FD_SET(socketfd, &readfds);
//最大文件描述符
int maxfd = socketfd;
//接收select返回值
int select_res = 0;
MSG msg;
ssize_t recvbytes = 0;
int acceptfd = -1;
int i = 0;
//定义一个数组,存储每次连接成功的客户端的信息
struct sockaddr_in save_addr[1024 - 4];
while (1)
{
tempfds = readfds;
//>0, 三个集合中成功触发事件的文件描述符个数 =0超时 =-1失败;
select_res = select(maxfd + 1, &tempfds, NULL, NULL, NULL);
if (select_res < 0)
{
printf("select error\n");
return -1;
}
else if (select_res == 0)
{
printf("select timeout\n");
return -1;
}
for (i = 0; i <= maxfd; i++)
{
//判断0~maxfd这些文件描述符在不在集合中
if (FD_ISSET(i, &tempfds) == 0)
{
continue;
}
//能运行到当前位置,则说明i所代表的文件描述符有事件产生
//判断是否是集合里关注的事件
if (socketfd == i)
{
printf("触发客户端连接事件:");
fflush(stdout);
//数据交互
acceptfd = accept(socketfd, (struct sockaddr *)&cin, &addrlen);
if (acceptfd == -1)
{
printf("acceptfd error\n");
return -1;
}
//网络字节序的IP-->点分十进制 网络字节序的port--->本机字节序
printf("[%s : %d] acceptfd = %d\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), acceptfd);
memset(history, 0, DATALEN);
sprintf(history,"[%s : %d] acceptfd[%d]",inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), acceptfd);
process_recv_history_request("connect", history);
//将cin存储到 save_addr数组对应的位置,
// acceptfd==4,则存储到下标为0,acceptfd==5,存储到下标为1,acceptfd==n,则存储到下标为n-4的位置
save_addr[acceptfd - 4] = cin;
//将acceptfd添加到集合中
FD_SET(acceptfd, &readfds);
//更新maxfd
maxfd = maxfd > acceptfd ? maxfd : acceptfd;
}
else
{
//客户端交互事件
bzero(&msg, sizeof(MSG));
recvbytes = recv(i, &msg, sizeof(MSG), 0);
if (recvbytes == -1)
{
// <0 错误
printf("recv error\n");
continue;
}
else if (recvbytes == 0)
{
// ==0
printf("[%s : %d] acceptfd = %d client off-line\n",
inet_ntoa(save_addr[i - 4].sin_addr), ntohs(save_addr[i - 4].sin_port), i);
memset(history, 0, DATALEN);
sprintf(history,"[%s : %d] acceptfd = [%d]",inet_ntoa(save_addr[i - 4].sin_addr), ntohs(save_addr[i - 4].sin_port), i);
process_recv_history_request("lost connect", history);
//关闭文件描述符
close(i);
//将文件描述符从集合中剔除
FD_CLR(i, &readfds);
//更新maxfd
for (int i = maxfd; i > 0; i--)
{
if (FD_ISSET(i, &readfds))
{
maxfd = i;
break;
}
}
printf("peer shutdown.\n");
}
else
{
//处理客户端请求
process_client_request(i, &msg);
}
}
}
}
close(socketfd);
return 0;
}
void do_admin_query(int sockfd, MSG *msg);
void do_admin_modification(int sockfd, MSG *msg);
void do_admin_adduser(int sockfd, MSG *msg);
void do_admin_deluser(int sockfd, MSG *msg);
void do_admin_history(int sockfd, MSG *msg);
void do_admin_list(int sockfd, MSG *msg);
void admin_menu(int sockfd, MSG *msg);
void do_user_query(int sockfd, MSG *msg);
void do_user_modification(int sockfd, MSG *msg);
void user_menu(int sockfd, MSG *msg);
int admin_or_user_login(int sockfd, MSG *msg);
int do_login(int socketfd);
#include "common.h"
#include "client.h"
/**************************************
*函数名:do_query
*参 数:消息结构体
*功 能:管理员查询
****************************************/
void do_admin_query(int sockfd, MSG *msg)
{
system("clear");
memset(msg, 0, sizeof(MSG));
msg->msgtype = ADMIN_QUERY;
char name[NAMELEN] = "";
printf("Please enter find no:");
scanf("%s", name);
while (getchar() != '\n')
;
strcpy(msg->recvmsg, name);
//发送查询请求
if (send(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the server error\n");
return;
}
//接受服务器响应
while (1)
{
recv(sockfd, msg, sizeof(MSG), 0);
if (!strncmp(msg->recvmsg, "end", 3))
{
printf("find success\n");
return;
}
if (!strncmp(msg->recvmsg, "no", 2))
{
printf("find error\n");
return;
}
printf("----------------------------------\n");
printf("staffno :%d\nusertype:%d\nname :%s\npasswd :%s\nage :%d\nphone :%s\naddr :%s\nwork :%s\ndate :%s\nlevel :%d\nsalary :%d\n", msg->info.no, msg->info.usertype, 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);
printf("----------------------------------\n");
}
}
/**************************************
*函数名:admin_modification
*参 数:消息结构体
*功 能:管理员修改
****************************************/
void do_admin_modification(int sockfd, MSG *msg) //管理员修改
{
system("clear");
memset(msg, 0, sizeof(MSG));
msg->msgtype = ADMIN_MODIFY;
int opt = 0;
int tem;
char str1[NAMELEN] = "";
char str2[DATALEN] = "";
char str3[PASSLEN] = "";
printf("please enter user name:");
scanf("%s",msg->username);
printf("1:no\n2:usertype\n3:name\n4:passwd\n5:age\n6:phone\n7:addr\n8:work\n9:date\n10:level\n11:salary\nplease enter change option:");
scanf("%d", &opt);
while(getchar()!='\n');
switch (opt)
{
case 1:
msg->flags = 1;
printf("please enter no:");
scanf("%d", &tem);
msg->info.no = tem;
break;
case 2:
msg->flags = 2;
printf("please enter usertype:");
scanf("%d", &tem);
msg->info.usertype = tem;
break;
case 3:
msg->flags = 3;
printf("please enter name:");
fgets(str1,NAMELEN,stdin);
str1[strlen(str1)-1]='\0';
strcpy(msg->info.name, str1);
break;
case 4:
msg->flags = 4;
printf("please enter passwd:");
fgets(str3,PASSLEN,stdin);
str3[strlen(str3)-1]='\0';
strcpy(msg->info.passwd, str1);
break;
case 5:
msg->flags = 5;
printf("please enter age:");
scanf("%d", &tem);
msg->info.age = tem;
break;
case 6:
msg->flags = 6;
printf("please enter phone:");
fgets(str1,NAMELEN,stdin);
str1[strlen(str1)-1]='\0';
strcpy(msg->info.phone, str1);
break;
case 7:
msg->flags = 7;
printf("please enter addr:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.addr, str2);
break;
case 8:
msg->flags = 8;
printf("please enter work:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.work, str2);
break;
case 9:
msg->flags = 9;
printf("please enter date:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.date, str2);
break;
case 10:
msg->flags = 10;
printf("please enter level:");
scanf("%d", &tem);
msg->info.level = tem;
break;
case 11:
msg->flags = 11;
printf("please enter salary:");
scanf("%d", &tem);
msg->info.salary = tem;
break;
default:
printf("enter error\n");
return;
}
if (send(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the server error\n");
return;
}
system("clear");
recv(sockfd, msg, sizeof(MSG), 0);
if (!strncmp(msg->recvmsg, "ok", 2))
{
printf("user change success\n");
return;
}
else if(!strncmp(msg->recvmsg, "no", 2))
{
printf("user change error\n");
return;
}
}
/**************************************
*函数名:admin_adduser
*参 数:消息结构体
*功 能:管理员创建用户
****************************************/
void do_admin_adduser(int sockfd, MSG *msg) //管理员添加用户
{
system("clear");
int tem;
char str1[NAMELEN] = "";
char str2[DATALEN] = "";
char str3[PASSLEN] = "";
memset(msg, 0, sizeof(MSG));
msg->msgtype = ADMIN_ADDUSER;
printf("please enter no:");
scanf("%d", &tem);
msg->info.no = tem;
printf("please enter usertype:");
scanf("%d", &tem);
msg->info.usertype = tem;
while (getchar() != '\n');
printf("please enter name:");
fgets(str1,NAMELEN,stdin);
str1[strlen(str1)-1]='\0';
strcpy(msg->info.name, str1);
printf("please enter passwd:");
fgets(str3,PASSLEN,stdin);
str3[strlen(str3)-1]='\0';
strcpy(msg->info.passwd, str3);
printf("please enter age:");
scanf("%d", &tem);
msg->info.age = tem;
while (getchar() != '\n');
printf("please enter phone:");
fgets(str1,NAMELEN,stdin);
str1[strlen(str1)-1]='\0';
strcpy(msg->info.phone, str1);
printf("please enter addr:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.addr, str2);
printf("please enter work:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.work, str2);
printf("please enter date:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.date, str2);
printf("please enter level:");
scanf("%d", &tem);
msg->info.level = tem;
printf("please enter salary:");
scanf("%d", &tem);
msg->info.salary = tem;
if (send(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the server error\n");
return;
}
recv(sockfd, msg, sizeof(MSG), 0);
if (!strncmp(msg->recvmsg, "ok", 2))
{
printf("user add success\n");
return;
}
else if (!strncmp(msg->recvmsg, "no", 2))
{
printf("user add error\n");
return;
}
printf("user add error\n");
}
/**************************************
*函数名:admin_deluser
*参 数:消息结构体
*功 能:管理员删除用户
****************************************/
void do_admin_deluser(int sockfd, MSG *msg) //管理员删除用户
{
system("clear");
msg->msgtype = ADMIN_DELUSER;
int no = 0;
printf("pelase enter delete user NO:");
scanf("%d", &no);
msg->info.no = no;
if (send(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the server error\n");
return;
}
recv(sockfd, msg, sizeof(MSG), 0);
if (!strncmp(msg->recvmsg, "ok", 2))
{
printf("user delete success\n");
return;
}
else if (!strncmp(msg->recvmsg, "no", 2))
{
printf("user delete error\n");
return;
}
}
/**************************************
*函数名:do_history
*参 数:消息结构体
*功 能:管理员查看历史记录
****************************************/
void do_admin_history(int sockfd, MSG *msg)
{
system("clear");
memset(msg, 0, sizeof(MSG));
msg->msgtype = ADMIN_HISTORY;
putchar(10);
printf(" %s | %s | %s \n","data","time","log");
if (send(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the server error\n");
return;
}
while (1)
{
recv(sockfd, msg, sizeof(MSG), 0);
if (msg->flags == 1)
{
printf("find success\n");
break;
}
if (msg->flags == 2)
{
printf("find error\n");
break;
}
printf("%s",msg->recvmsg);
send(sockfd, msg, sizeof(MSG), 0);
}
}
void do_admin_list(int sockfd, MSG *msg)
{
system("clear");
memset(msg, 0, sizeof(MSG));
msg->msgtype = ADMIN_LIST;
char name[NAMELEN] = "";
//发送查询请求
if (send(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the server error\n");
return;
}
//接受服务器响应
while (1)
{
recv(sockfd, msg, sizeof(MSG), 0);
if (!strncmp(msg->recvmsg, "endd", 4))
{
printf("find success\n");
return;
}
if (!strncmp(msg->recvmsg, "no", 2))
{
printf("find error\n");
return;
}
//printf("%d\t%d\t%s\t%s\t%d\t%s\t%s\t%s\t%s\t%d\t%d\n", msg->info.no, msg->info.usertype, 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);
printf("----------------------------------\n");
printf("staffno :%d\nusertype:%d\nname :%s\npasswd :%s\nage :%d\nphone :%s\naddr :%s\nwork :%s\ndate :%s\nlevel :%d\nsalary :%d\n", msg->info.no, msg->info.usertype, 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);
printf("----------------------------------\n");
send(sockfd, msg, sizeof(MSG), 0);
}
}
/**************************************
*函数名:admin_menu
*参 数:套接字、消息结构体
*功 能:管理员菜单
****************************************/
void admin_menu(int sockfd, MSG *msg)
{
int op = -1;
printf(" ************ 1 find ************\n");
printf(" ************ 2 change ************\n");
printf(" ************ 3 add ************\n");
printf(" ************ 4 delete ************\n");
printf(" ************ 5 list ************\n");
printf(" ************ 6 clean ************\n");
printf(" ************ 7 history ************\n");
printf(" ************ 0 quit ************\n");
printf("please enter your option:");
scanf("%d", &op);
while(getchar()!='\n');
if(op < 0 || op > 7)
{
system("clear");
printf("输入错误 请重新输入\n");
admin_menu(sockfd,msg);
}
switch (op)
{
case 0:
system("clear");
do_login(sockfd);
break;
case 1:
do_admin_query(sockfd, msg);
break;
case 2:
do_admin_modification(sockfd, msg);
break;
case 3:
do_admin_adduser(sockfd, msg);
break;
case 4:
do_admin_deluser(sockfd, msg);
break;
case 5:
do_admin_list(sockfd, msg);
break;
case 6:
system("clear");
break;
case 7:
do_admin_history(sockfd,msg);
break;
default:
printf("enter error\n");
return;
}
}
/**************************************
*函数名:do_query
*参 数:消息结构体
*功 能:用户查找
****************************************/
void do_user_query(int sockfd, MSG *msg)
{
system("clear");
memset(msg, 0, sizeof(MSG));
msg->msgtype = USER_QUERY;
strcpy(msg->username, user_name);
strcpy(msg->passwd,user_passwd);
//发送查询请求
if (send(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the server error\n");
return;
}
//接受服务器响应
while(1)
{
recv(sockfd, msg, sizeof(MSG), 0);
if (!strncmp(msg->recvmsg, "end", 3))
{
printf("find success\n");
return;
}
if (!strncmp(msg->recvmsg, "no", 2))
{
printf("find error\n");
return;
}
printf("----------------------------------\n");
printf("staffno :%d\nusertype:%d\nname :%s\npasswd :%s\nage :%d\nphone :%s\naddr :%s\nwork :%s\ndate :%s\nlevel :%d\nsalary :%d\n", msg->info.no, msg->info.usertype, 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);
printf("----------------------------------\n");
}
}
/**************************************
*函数名:do_modification
*参 数:消息结构体
*功 能:用户修改
****************************************/
void do_user_modification(int sockfd, MSG *msg)
{
system("clear");
memset(msg, 0, sizeof(MSG));
msg->msgtype = USER_MODIFY;
strcpy(msg->username, user_name);
strcpy(msg->passwd,user_passwd);
int opt = 0;
int tem;
char str1[NAMELEN] = "";
char str2[DATALEN] = "";
char str3[PASSLEN] = "";
printf("1:no\n2:usertype(Please contact the administrator)\n3:name\n4:passwd\n5:age\n6:phone\n7:addr\n8:work\n9:date\n10:level\n11:salary\nplease enter change option:");
scanf("%d", &opt);
while(getchar()!='\n');
switch (opt)
{
case 1:
msg->flags = 1;
printf("please enter no:");
scanf("%d", &tem);
msg->info.no = tem;
break;
case 2:
msg->flags = 2;
printf("please enter usertype:");
scanf("%d", &tem);
msg->info.usertype = tem;
break;
case 3:
msg->flags = 3;
printf("please enter name:");
fgets(str1,NAMELEN,stdin);
str1[strlen(str1)-1]='\0';
strcpy(msg->info.name, str1);
break;
case 4:
msg->flags = 4;
printf("please enter passwd:");
fgets(str3,PASSLEN,stdin);
str3[strlen(str3)-1]='\0';
strcpy(msg->info.passwd, str3);
break;
case 5:
msg->flags = 5;
printf("please enter age:");
scanf("%d", &tem);
msg->info.age = tem;
break;
case 6:
msg->flags = 6;
printf("please enter phone:");
fgets(str1,NAMELEN,stdin);
str1[strlen(str1)-1]='\0';
strcpy(msg->info.phone, str1);
break;
case 7:
msg->flags = 7;
printf("please enter addr:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.addr, str2);
break;
case 8:
msg->flags = 8;
printf("please enter work:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.work, str2);
break;
case 9:
msg->flags = 9;
printf("please enter date:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.date, str2);
break;
case 10:
msg->flags = 10;
printf("please enter level:");
scanf("%d", &tem);
msg->info.level = tem;
break;
case 11:
msg->flags = 11;
printf("please enter salary:");
scanf("%d", &tem);
msg->info.salary = tem;
break;
default:
printf("enter error\n");
return;
}
if (send(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the server error\n");
return;
}
system("clear");
recv(sockfd, msg, sizeof(MSG), 0);
if (!strncmp(msg->recvmsg, "ok", 2))
{
printf("user change success\n");
return;
}
else if(!strncmp(msg->recvmsg, "no", 2))
{
printf("user change error\n");
return;
}
}
/**************************************
*函数名:user_menu
*参 数:消息结构体
*功 能:用户菜单
****************************************/
void user_menu(int sockfd, MSG *msg)
{
int op = -1;
printf(" ************ 1 find ************\n");
printf(" ************ 2 change ************\n");
printf(" ************ 3 clean ************\n");
printf(" ************ 0 quit ************\n");
printf("please enter your option:");
scanf("%d", &op);
while(getchar()!='\n');
if(op < 0 || op > 3)
{
system("clear");
printf("输入错误 请重新输入\n");
user_menu(sockfd,msg);
}
switch (op)
{
case 0:
system("clear");
do_login(sockfd);
break;
case 1:
do_user_query(sockfd, msg);
break;
case 2:
do_user_modification(sockfd, msg);
break;
case 3:
system("clear");
break;
default:
printf("enter error\n");
break;
}
}
int admin_or_user_login(int sockfd, MSG *msg)
{
//输入用户名和密码
memset(msg->username, 0, NAMELEN);
printf("请输入用户名:");
scanf("%s", msg->username);
getchar();
memset(msg->passwd, 0, DATALEN);
printf("请输入密码: ");
scanf("%s", msg->passwd);
getchar();
strcpy(user_name,msg->username);
strcpy(user_passwd,msg->passwd);
//发送登陆请求
if (send(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("Sending the account to the server error\n");
return -1;
}
//接受服务器响应
recv(sockfd, msg, sizeof(MSG), 0);
//判断是否登陆成功
if (strncmp(msg->recvmsg, "OK", 2) == 0)
{
if (msg->usertype == ADMIN)
{
system("clear");
printf("亲爱的管理员,欢迎您登陆员工管理系统!\n");
while (1)
{
admin_menu(sockfd, msg);
}
}
else if (msg->usertype == USER)
{
system("clear");
printf("亲爱的用户,欢迎您登陆员工管理系统!\n");
while (1)
{
user_menu(sockfd, msg);
}
}
}
else
{
printf("登陆失败!%s\n", msg->recvmsg);
admin_or_user_login(sockfd,msg);
}
return 0;
}
/************************************************
*函数名:do_login
*参 数:套接字、消息结构体
*返回值:是否登陆成功
*功 能:登陆
*************************************************/
int do_login(int socketfd)
{
int n;
MSG msg;
while (1)
{
printf("**********************************\n");
printf("******** 1: 管理员模式 ********\n");
printf("******** 2:普通用户模式 ********\n");
printf("******** 0: 退出 ********\n");
printf("**********************************\n");
printf("请输入您的选择(数字)>> ");
scanf("%d", &n);
while(getchar()!='\n');
if(n < 0 || n > 2)
{
system("clear");
printf("输入错误 请重新输入\n");
do_login(socketfd);
}
switch (n)
{
case 1:
//管理员模式登录
msg.msgtype = ADMIN_LOGIN; // 1
msg.usertype = ADMIN; // 0
break;
case 2:
//普通用户登录
msg.msgtype = USER_LOGIN;
msg.usertype = USER;
break;
case 0:
//退出
msg.msgtype = QUIT;
if (send(socketfd, &msg, sizeof(MSG), 0) < 0)
{
perror("do_login send");
return -1;
}
close(socketfd);
exit(0);
default:
printf("您的输入有误,请重新输入\n");
}
admin_or_user_login(socketfd, &msg);
}
}
int main(int argc, const char *argv[])
{
// socket->填充->绑定->监听->等待连接->数据交互->关闭
system("clear");
int socketfd;
//创建网络通信的套接字 流式套接字
if (-1 == (socketfd = socket(AF_INET, SOCK_STREAM, 0)))
{
printf("socket error\n");
return -1;
}
printf("socket success\n");
//填充网络结构体
//填充服务器网路信息结构体
struct sockaddr_in sin;
//填充为IPV4地址
sin.sin_family = AF_INET;
//填充服务器IP
sin.sin_addr.s_addr = inet_addr(IP);
//填充服务器端口号
sin.sin_port = htons(atoi(PORT));
//连接服务器
if (-1 == connect(socketfd, (struct sockaddr *)&sin, sizeof(sin)))
{
printf("connect error\n");
return -1;
}
printf("connect suceess\n");
//登陆
do_login(socketfd);
//关闭套接字
close(socketfd);
return 0;
}
员工信息管理系统 测试