概述:
1)服务器负责管理所有员工表单(以数据库形式或文件形式都可),其他客户端可通过网络连接服务器来查询员工表单。
2)需要账号密码登陆,其中需要区分管理员账号还是普通用户账号。
3)管理员账号可以查看、修改员工表单,管理员要负责管理所有的普通用户。
4)普通用户只能查询修改与本人有关的相关信息,其他员工信息(出于保密原则)不得泄露。
5)有查询历史记录功能。
6)能同时处理多台客户端的请求功能。
流程图:
服务器流程图:
客户端流程图:
原码
为了防止出现函数定义顺序问题统一定义了在服务器与客户端中分别定义了.h文件
server.h
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);
client.h
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);
功能代码
server.c
#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;
}
client.c
#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("请输入编号:");
scanf("%d", &tem);
msg->info.no = tem;
printf("请输入用户类型:");
scanf("%d", &tem);
msg->info.usertype = tem;
while (getchar() != '\n');
printf("请输入用户名:");
fgets(str1,NAMELEN,stdin);
str1[strlen(str1)-1]='\0';
strcpy(msg->info.name, str1);
printf("请输入密码:");
fgets(str3,PASSLEN,stdin);
str3[strlen(str3)-1]='\0';
strcpy(msg->info.passwd, str3);
printf("请输入年龄:");
scanf("%d", &tem);
msg->info.age = tem;
while (getchar() != '\n');
printf("请输入手机号:");
fgets(str1,NAMELEN,stdin);
str1[strlen(str1)-1]='\0';
strcpy(msg->info.phone, str1);
printf("请输入地址:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.addr, str2);
printf("请输入工作:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.work, str2);
printf("请输入入职年月:");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.date, str2);
printf("请输入等级:");
scanf("%d", &tem);
msg->info.level = tem;
printf("请输入工资:");
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("请输入需要删除的用户编号:");
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 查找用户 ************\n");
printf(" ************ 2 更改用户信息 ************\n");
printf(" ************ 3 添加用户 ************\n");
printf(" ************ 4 删除用户 ************\n");
printf(" ************ 5 用户列表 ************\n");
printf(" ************ 6 清空界面 ************\n");
printf(" ************ 7 历史记录 ************\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("请输入编号:");
scanf("%d", &tem);
msg->info.no = tem;
break;
case 2:
msg->flags = 2;
printf("请输入用户类型:");
scanf("%d", &tem);
msg->info.usertype = tem;
break;
case 3:
msg->flags = 3;
printf("请输入用户名:");
fgets(str1,NAMELEN,stdin);
str1[strlen(str1)-1]='\0';
strcpy(msg->info.name, str1);
break;
case 4:
msg->flags = 4;
printf("请输入密码:");
fgets(str3,PASSLEN,stdin);
str3[strlen(str3)-1]='\0';
strcpy(msg->info.passwd, str3);
break;
case 5:
msg->flags = 5;
printf("请输入年龄:");
scanf("%d", &tem);
msg->info.age = tem;
break;
case 6:
msg->flags = 6;
printf("请输入手机号");
fgets(str1,NAMELEN,stdin);
str1[strlen(str1)-1]='\0';
strcpy(msg->info.phone, str1);
break;
case 7:
msg->flags = 7;
printf("请输入地址");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.addr, str2);
break;
case 8:
msg->flags = 8;
printf("请输入工作");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.work, str2);
break;
case 9:
msg->flags = 9;
printf("请输入入职年月");
fgets(str2,DATALEN,stdin);
str2[strlen(str2)-1]='\0';
strcpy(msg->info.date, str2);
break;
case 10:
msg->flags = 10;
printf("请输入等级:");
scanf("%d", &tem);
msg->info.level = tem;
break;
case 11:
msg->flags = 11;
printf("请输入工资:");
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 查找用户 ************\n");
printf(" ************ 2 更改用户信息 ************\n");
printf(" ************ 3 清空界面 ************\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;
}
common.h
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sqlite3.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sqlite3.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <pthread.h>
#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 "192.168.250.100"
#define IP "192.168.250.100"
#define PORT "8888"
char user_name[NAMELEN]; //姓名
char user_passwd[PASSLEN]; //登陆密码
char history[DATALEN+100];
#endif
测试结果
2022-10-31 11-09-51