一百二十二、信息管理系统:百川仓储管理
122.1 UI界面
122.2 思路
- 客户端: 用户权限有两种类型,一种是用户权限,一种是管理员权限,登录时服务器端会根据数据库查询到的此用户名的权限返回不同的结果,客户端会根据这个结果打开不同的操作界面。
用户 可以进行登录、注册,存取物品,查询个人信息,修改密码,查看仓库库存,查看个人操作记录;
管理员 可以进行登录,存取物品,查看仓库库存,查看所有用户,修改用户密码,提升用户权限为管理员,删除用户,添加用户,查看所有操作记录; - 服务器端: 服务器端根据不同的数据包进行不同的操作,然后发回不同的数据包。在服务器端使用set容器防止使用者重复登录— —每次登录成功时都会往容器中加入这个用户名,每次登录时都会检查这个容器中是否有这个名字,如果有,那就登录失败;断开链接时会删除这个用户名。每次登录时都会记录用户名,方便后面进行存放历史记录。
- 数据库: 数据库用的是 sqlite3 ,数据库中有三个表,用户表(user)、物品信息表(item_info)、历史记录表(history)。
- 传输层协议: TCP。
这个项目可以部署在云服务器上:
服务器代码在云服务器运行,服务器端IP绑定为云服务器的内网IP;
客户端连接的服务器IP绑定为云服务器的公网IP。
客户端可以通过工具打包成一个exe文件,步骤可以去B站搜搜
122.3 代码
-
客户端代码文件太多了,就不直接放代码了,直接上传项目包
-
服务器端代码有点长
122.4 服务器端代码
main.cpp
#include "server.h"
sqlite3 *sqldb = nullptr;
int main(int argc, const char *argv[])
{
if (sqlite3_open("../warehouse.db", &sqldb) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_open error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), sqlite3_errmsg(sqldb), __LINE__);
return -1;
}
printf("数据库打开成功\n");
// 创建用户表
char sql_str[128] = "";
strcpy(sql_str, "CREATE TABLE if not exists user(uname char,passwd char,privilege char,signin_time char)");
char *error_msg = NULL;
if (sqlite3_exec(sqldb, sql_str, NULL, NULL, &error_msg) != SQLITE_OK)
{
fprintf(stderr, "create table error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), error_msg, __LINE__);
return -1;
}
printf("用户表创建成功\n");
// 创建历史记录表
strcpy(sql_str, "CREATE TABLE if not exists history\
(uname char,operation char,Obj char,optime char,oper_ip char)");
char *error_msg2 = NULL;
if (sqlite3_exec(sqldb, sql_str, NULL, NULL, &error_msg2) != SQLITE_OK)
{
fprintf(stderr, "create table error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), error_msg2, __LINE__);
return -1;
}
printf("历史记录表创建成功\n");
// 创建物品信息表
strcpy(sql_str, "CREATE TABLE if not exists item_info\
(item_name char,supplier char,numb int,input_name char,input_time char)");
char *error_msg3 = NULL;
if (sqlite3_exec(sqldb, sql_str, NULL, NULL, &error_msg3) != SQLITE_OK)
{
fprintf(stderr, "create table error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), error_msg3, __LINE__);
return -1;
}
printf("物品信息表创建成功\n");
// 创建流式套接字 服务器
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("套接字创建成功 server_fd = %d\n", server_fd);
// 允许端口快速复用
int reuse = 1;
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速复用成功\n");
// 绑定服务器的地址信息 必须绑定
struct sockaddr_in server_in; // 用于绑定本主机的信息
server_in.sin_family = AF_INET; // 必须填 AF_UNIX
// 因为前面创建流式套接字用的是 IPv4
server_in.sin_port = htons(SERVER_PORT); // 指定端口号
server_in.sin_addr.s_addr = inet_addr(SERVER_IP); // 绑定本机IP
if (bind(server_fd, (struct sockaddr *)&server_in, sizeof(server_in)) < 0)
{
ERR_MSG("bin");
return -1;
}
printf("bind 成功\n");
// 将套接字转换为被动监听状态
if (listen(server_fd, 256) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("listen 成功\n");
// 获取连接成功的客户端信息,生成一个新的文件描述符
// 该文件描述符才是与客户端通信的文件描述符
client_info info; // 用于存放接收的客户端的信息
// struct sockaddr_in client_in; // 用于存放接收的客户端的信息
socklen_t addrlen = sizeof(info.c_in); // 用于存放客户端传来的信息的长度
int new_fd;
while (1)
{
new_fd = accept(server_fd, (struct sockaddr *)&info.c_in, &addrlen); // 连接客户端
if (new_fd < 0)
{
ERR_MSG("accept");
return -1;
}
info.new_fd = new_fd;
// 输出客户端IP和端口号
printf("[%s : %d]已连接 new_fd = %d \n", inet_ntoa(info.c_in.sin_addr), ntohs(info.c_in.sin_port), new_fd);
// 创建线程处理客户端发来的连接和数据
pthread_t tid1;
if (pthread_create(&tid1, NULL, thread, (void *)&info) != 0)
{
fprintf(stderr, "线程创建错误 __%d__\n", __LINE__);
}
pthread_detach(tid1);
}
// 关闭套接字
close(server_fd);
close(new_fd);
return 0;
}
server.h
#ifndef __SERVER_H__
#define __SERVER_H__
#include <my_head.h>
#include <iostream>
#include <string>
#include <set>
#define DATA_SIZE 1500
#define SERVER_IP "内网IP"
// #define SERVER_IP "127.0.0.1" // 服务器IP
#define SERVER_PORT 6666
#define ROOT "zhk"
typedef struct thread_arg
{
int new_fd;
struct sockaddr_in c_in;
} client_info;
// 外部变量,打开服务器
extern sqlite3 *sqldb;
enum
{
LOGIN = 1, // 登录
SIGNIN, // 注册
CHANGE_PASSWD, // 修改密码
SAVE, // 存物品
GET_OUT, // 取物品
CHECK_ITEMS, // 查看物品
CHECK_HISTORY, // 查看历史记录
CHANGE_PRIVILEGE, // 修改权限
CHECK_INFO, // 查看个人信息
DELETE_USER, // 删除用户
FIND_ALL_USER, // 查看所有用户
LOGIN_OR_SIGNIN_SUCCESS = 11, // 普通用户 登录/注册 成功
ADMIN_LOGIN_SUCESS, // 管理员登录成功
LOGIN_OR_SIGNIN_FAILURE, // 登录/注册 失败
CHANGE_PASSWD_SUCCESS, // 密码修改成功
CHANGE_PASSWD_FAILURE, // 密码修改失败
CHANGE_PRIVILEGE_SUCESS, // 权限修改成功
CHANGE_PRIVILEGE_FAILURE, // 权限修改失败
DELETE_USER_SUCESS, // 删除用户成功
DELETE_USER_FAILURE, // 删除用户失败
SAVE_SUCESS = 21, // 存放成功
SAVE_FAILURE, // 存放失败
GET_OUT_SUCESS, // 取出成功
GET_OUT_FAILURE, // 取出失败
CHECK_SUCESS, // 查看成功
CHECK_FAILURE, // 查看失败
};
// 线程处理 与客户端连接
void *thread(void *arg);
// 处理 查看物品 功能
void deal_CHECK_ITEMS(char *buff, client_info &cli, char *name);
// 处理 查看历史记录 功能
void deal_CHECK_HISTORY(char *buff, client_info &cli, char *name);
// 处理 查询所有用户 功能
void deal_FIND_ALL_USER(char *buff, client_info &cli, char *name);
// 处理 修改权限 功能
void deal_CHANGE_PRIVILEGE(char *buff, client_info &cli, char *name);
// 处理 删除用户 功能
void deal_DELETE_USER(char *buff, client_info &cli, char *name);
// 处理 修改密码 功能
void deal_CHANGE_PASSWD(char *buff, client_info &cli, char *name);
// 处理 查看 个人信息 功能
void deal_CHECK_INFO(char *buff, client_info &cli, char *name);
// 处理 取出物品 功能
void deal_GET_OUT(char *buff, client_info &cli, char *name);
// 处理 存放物品 功能
void deal_SAVE(char *buff, client_info &cli, char *uname);
// 处理登录功能
void deal_LOGIN(char *buff, client_info &cli, char *uname);
// 处理注册功能
void deal_SIGNIN(char *buff, client_info &cli);
// 查询历史记录
int deal_find_history(int new_fd, char *buff, struct sockaddr_in client_in, sqlite3 *sqldb);
// 与服务器通信
// 获取当前时间,返回字符串
char *get_time(char *now_time);
// 获取服务器信息,返回字符串
char *get_client_info(struct sockaddr_in client_in, char *info);
// 数据库操作
// 查询数据
int select_data_ret_num(char *sql_str, sqlite3 *sqldb);
// 插入数据
int insert_data(char *sql_str, sqlite3 *sqldb);
#endif
server.cpp
#include "server.h"
using namespace std;
set<string> signin_set;
void *thread(void *arg)
{
client_info th_arg = *((client_info *)arg);
// 存放 接收的数据
char buff[128];
// 操作码
char *opcode = buff;
char uname[128];
ssize_t res = 0;
while (1)
{
// 清空暂存区
bzero(buff, sizeof(buff));
// 接收数据
res = read(th_arg.new_fd, buff, sizeof(buff));
if (res < 0)
{
ERR_MSG("recv");
break;
}
// 写端关闭了,即客户端关闭
else if (0 == res)
{
printf("[ %s : %d ]客户端断开链接\n", inet_ntoa(th_arg.c_in.sin_addr),
ntohs(th_arg.c_in.sin_port));
goto THREAD_END;
}
// 对接收的消息进行分类处理
switch (*opcode)
{
case LOGIN: // 登录请求
deal_LOGIN(buff, th_arg, uname);
break;
case SIGNIN: // 注册请求
deal_SIGNIN(buff, th_arg);
break;
case CHANGE_PASSWD: // 修改密码
deal_CHANGE_PASSWD(buff, th_arg, uname);
break;
case SAVE: // 存物品
deal_SAVE(buff, th_arg, uname);
break;
case GET_OUT: // 取物品
deal_GET_OUT(buff, th_arg, uname);
break;
case CHECK_ITEMS: // 查看物品
deal_CHECK_ITEMS(buff, th_arg, uname);
break;
case CHECK_HISTORY: // 查看历史记录
deal_CHECK_HISTORY(buff, th_arg, uname);
break;
case CHANGE_PRIVILEGE: // 修改权限
deal_CHANGE_PRIVILEGE(buff, th_arg, uname);
break;
case CHECK_INFO: // 查询个人信息
deal_CHECK_INFO(buff, th_arg, uname);
break;
case DELETE_USER: // 删除用户
deal_DELETE_USER(buff, th_arg, uname);
break;
case FIND_ALL_USER: // 查看所有用户
deal_FIND_ALL_USER(buff, th_arg, uname);
break;
default:
break;
}
}
THREAD_END:
if (!signin_set.empty() && signin_set.find(uname) != signin_set.end())
{
signin_set.erase(uname);
}
close(th_arg.new_fd);
pthread_exit(NULL);
}
// 处理 查看物品 功能
void deal_CHECK_ITEMS(char *buff, client_info &cli, char *name)
{
// 获取客户传来的内容
char *item = buff + 1;
char *supplier = item + 1 + strlen(item);
char sql_str[256];
char ret_msg[512] = "CHECK_FAILURE";
sprintf(sql_str, "select * from item_info ");
// 如果 或物品, 或供应商,有任何一个存在,则加上where
if (strcmp(item, "") || strcmp(supplier, ""))
{
strcat(sql_str, "where ");
}
// SQL语句追加
if (strcmp(item, ""))
{
char item_cat[32] = "";
sprintf(item_cat, "item_name='%s' ", item);
strcat(sql_str, item_cat);
if (strcmp(supplier, ""))
{
char supplier_cat[32] = "";
sprintf(supplier_cat, "and supplier='%s' ", supplier);
strcat(sql_str, supplier_cat);
}
}
else
{
if (strcmp(supplier, ""))
{
char supplier_cat[32] = "";
sprintf(supplier_cat, "supplier='%s' ", supplier);
strcat(sql_str, supplier_cat);
}
}
// 查询数据库
char **result = nullptr;
int row = 0;
int column = 0;
char *errmsg = nullptr;
if (sqlite3_get_table(sqldb, sql_str, &result, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_get_table error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), sqlite3_errmsg(sqldb), __LINE__);
return;
}
for (int i = 1; i <= row; i++)
{
bzero(ret_msg, sizeof(ret_msg));
for (int j = 0; j < column; j++)
{
// printf("%s\t", result[(column * i) + j]);
strcat(ret_msg, result[(column * i) + j]);
strcat(ret_msg, "|");
}
strcat(ret_msg, "\n");
// 发送 修改用户权限 结果
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
}
char operation[32] = "";
sprintf(operation, "CHECK_ITEMS");
char now_time[64] = "";
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "insert into history (uname,operation,Obj,optime,oper_ip) values('%s','%s','%s','%s','%s');",
name, operation, item, get_time(now_time), inet_ntoa(cli.c_in.sin_addr));
insert_data(sql_str, sqldb);
}
// 处理 查看历史记录 功能
void deal_CHECK_HISTORY(char *buff, client_info &cli, char *name)
{
// 先确定当前登录用户是否是管理员权限
// 若不是管理员权限,则不将所有信息返回
bool flag = false;
// SQL语句
char sql_str[256];
char ret_msg[512];
// 查询这个人的权限
sprintf(sql_str, "select privilege from user where uname='%s';", name);
char **result = nullptr;
int row = 0;
int column = 0;
char *errmsg = nullptr;
if (sqlite3_get_table(sqldb, sql_str, &result, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_get_table error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), sqlite3_errmsg(sqldb), __LINE__);
return;
}
// 有这个人,且权限为管理员权限
if (row != 0 && strcmp(result[column], "admin") == 0)
{
flag = true;
}
// 获取客户端发来的消息,并进行拆分
char *uname = buff + 1;
char *item = uname + 1 + (strlen(uname));
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "select * from history ");
// 如果 用户名, 或物品,有任何一个存在,则加上where
if (strcmp(uname, "") || strcmp(item, "") || !flag)
{
strcat(sql_str, "where ");
}
if (flag)
{
if (strcmp(uname, ""))
{
char uname_cat[32] = "";
sprintf(uname_cat, "uname='%s' ", uname);
strcat(sql_str, uname_cat);
if (strcmp(item, ""))
{
char item_cat[32] = "";
sprintf(item_cat, "and Obj='%s' ", item);
strcat(sql_str, item_cat);
}
}
else
{
if (strcmp(item, ""))
{
char item_cat[32] = "";
sprintf(item_cat, "Obj='%s' ", item);
strcat(sql_str, item_cat);
}
}
}
else
{
uname = name;
char name_cat[32] = "";
sprintf(name_cat, "uname='%s' ", name);
strcat(sql_str, name_cat);
if (strcmp(item, ""))
{
char item_cat[32] = "";
sprintf(item_cat, "and Obj='%s' ", item);
strcat(sql_str, item_cat);
}
}
// 查询数据库
char **result2 = nullptr;
row = 0;
column = 0;
char *errmsg2 = nullptr;
if (sqlite3_get_table(sqldb, sql_str, &result2, &row, &column, &errmsg2) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_get_table error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), sqlite3_errmsg(sqldb), __LINE__);
return;
}
for (int i = 1; i <= row; i++)
{
bzero(ret_msg, sizeof(ret_msg));
for (int j = 0; j < column; j++)
{
// printf("%s\t", result[(column * i) + j]);
strcat(ret_msg, result2[(column * i) + j]);
strcat(ret_msg, "|");
}
strcat(ret_msg, "\n");
// 发送 修改用户权限 结果
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
}
char operation[32] = "";
sprintf(operation, "CHECK_HISTORY");
char now_time[64] = "";
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "insert into history (uname,operation,Obj,optime,oper_ip) values('%s','%s','%s','%s','%s');",
name, operation, uname, get_time(now_time), inet_ntoa(cli.c_in.sin_addr));
insert_data(sql_str, sqldb);
}
// 处理 查询所有用户 功能
void deal_FIND_ALL_USER(char *buff, client_info &cli, char *name)
{
char *uname = buff + 1;
char *privilege = uname + 1 + strlen(uname);
char sql_str[256];
char ret_msg[512] = "CHECK_FAILURE";
// 先加上查看的用户的权限
sprintf(sql_str, "select * from user where privilege='%s' ", privilege);
// 用户名
if (strcmp(uname, ""))
{
char uname_cat[32] = "";
sprintf(uname_cat, "and uname='%s' ", uname);
strcat(sql_str, uname_cat);
}
// 查询数据库
char **result = nullptr;
int row = 0;
int column = 0;
char *errmsg = nullptr;
if (sqlite3_get_table(sqldb, sql_str, &result, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_get_table error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), sqlite3_errmsg(sqldb), __LINE__);
return;
}
for (int i = 1; i <= row; i++)
{
bzero(ret_msg, sizeof(ret_msg));
for (int j = 0; j < column; j++)
{
// printf("%s\t", result[(column * i) + j]);
strcat(ret_msg, result[(column * i) + j]);
strcat(ret_msg, "|");
}
strcat(ret_msg, "\n");
printf("ret_msg = %s",ret_msg);
// 发送 修改用户权限 结果
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
}
char operation[32] = "";
sprintf(operation, "FIND_USER");
char now_time[64] = "";
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "insert into history (uname,operation,Obj,optime,oper_ip) values('%s','%s','%s','%s','%s');",
name, operation, uname, get_time(now_time), inet_ntoa(cli.c_in.sin_addr));
insert_data(sql_str, sqldb);
}
// 处理 修改权限 功能
void deal_CHANGE_PRIVILEGE(char *buff, client_info &cli, char *name)
{
char *uname = buff + 1;
char sql_str[256];
char ret_msg[64] = "CHANGE_PRIVILEGE_FAILURE";
/*
* 不可对ROOT权限用户操作
*/
if (!strcmp(uname, ROOT))
{
// 发送 删除用户
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
return;
}
// 先检查有没有这个用户,没有就返回 修改错误
sprintf(sql_str, "select * from user where uname='%s';", uname);
if (select_data_ret_num(sql_str, sqldb) != 0)
{
bzero(sql_str, sizeof(sql_str));
// 修改
sprintf(sql_str, "update user set privilege='admin' where uname='%s';", uname);
if (0 == insert_data(sql_str, sqldb))
{
bzero(ret_msg, sizeof(ret_msg));
strcpy(ret_msg, "CHANGE_PRIVILEGE_SUCESS");
}
}
// 发送 修改用户权限 结果
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
char operation[32] = "";
sprintf(operation, "CHANGE_PRIVILEGE");
char now_time[64] = "";
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "insert into history (uname,operation,Obj,optime,oper_ip) values('%s','%s','%s','%s','%s');",
name, operation, uname, get_time(now_time), inet_ntoa(cli.c_in.sin_addr));
insert_data(sql_str, sqldb);
}
// 处理 删除用户 功能
void deal_DELETE_USER(char *buff, client_info &cli, char *name)
{
char *uname = buff + 1;
char sql_str[256];
char ret_msg[64] = "DELETE_USER_FAILURE";
/*
* 不可对ROOT权限用户操作
*/
if (!strcmp(uname, ROOT))
{
// 发送 删除用户
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
return;
}
// 先检查有没有这个用户,没有就返回 删除错误
sprintf(sql_str, "select * from user where uname='%s';", uname);
if (select_data_ret_num(sql_str, sqldb) != 0)
{
bzero(sql_str, sizeof(sql_str));
// 删除
sprintf(sql_str, "delete from user where uname='%s';", uname);
if (0 == insert_data(sql_str, sqldb))
{
bzero(ret_msg, sizeof(ret_msg));
strcpy(ret_msg, "DELETE_USER_SUCESS");
}
}
// 发送 删除用户 结果
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
char operation[32] = "";
sprintf(operation, "DELETE_USER");
char now_time[64] = "";
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "insert into history (uname,operation,Obj,optime,oper_ip) values('%s','%s','%s','%s','%s');",
name, operation, uname, get_time(now_time), inet_ntoa(cli.c_in.sin_addr));
insert_data(sql_str, sqldb);
}
// 处理 修改密码 功能
void deal_CHANGE_PASSWD(char *buff, client_info &cli, char *name)
{
char *uname = buff + 1;
char *pwd = buff + 2 + (strlen(buff + 1));
char *new_pwd = pwd + 1 + strlen(pwd);
// 先查看用户名和密码对不对
char sql_str[256];
sprintf(sql_str, "select * from user where uname='%s' and passwd='%s';", uname, pwd);
char ret_msg[64] = "CHANGE_PASSWD_FAILURE";
/*
* 不可对ROOT权限用户操作
*/
if (!strcmp(uname, ROOT))
{
// 发送 删除用户
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
return;
}
// 如果这个用户名和密码都正确对应,则进行修改
if (0 != select_data_ret_num(sql_str, sqldb))
{
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "update user set passwd='%s' where uname='%s' and passwd='%s';", new_pwd, uname, pwd);
if (0 == insert_data(sql_str, sqldb))
{
strcpy(ret_msg, "CHANGE_PASSWD_SUCCESS");
}
}
// 发送 存放结果
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
char operation[32] = "";
sprintf(operation, "CHANGE_PASSWD_to_[%s]", new_pwd);
char now_time[64] = "";
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "insert into history (uname,operation,Obj,optime,oper_ip) values('%s','%s','%s','%s','%s');",
name, operation, uname, get_time(now_time), inet_ntoa(cli.c_in.sin_addr));
insert_data(sql_str, sqldb);
}
// 处理 查看 个人信息 功能
void deal_CHECK_INFO(char *buff, client_info &cli, char *name)
{
char *uname = buff + 1;
char ret_msg[128] = "CHECK_FAILURE";
// 俩名字不相同
if (strcmp(uname, name) != 0)
{
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
return;
}
// 根据名字查询权限和注册时间
char sql_str[256];
sprintf(sql_str, "select privilege,signin_time from user where uname='%s';", uname);
char **result = nullptr;
int row = 0;
int column = 0;
char *errmsg = nullptr;
if (sqlite3_get_table(sqldb, sql_str, &result, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_get_table error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), sqlite3_errmsg(sqldb), __LINE__);
return;
}
bzero(ret_msg, sizeof(ret_msg));
sprintf(ret_msg, "%s|%s", result[2], result[3]);
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
// 存入历史记录
char operation[32] = "";
sprintf(operation, "CHECK_INFO");
char now_time[64] = "";
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "insert into history (uname,operation,Obj,optime,oper_ip) values('%s','%s','%s','%s','%s');",
name, operation, name, get_time(now_time), inet_ntoa(cli.c_in.sin_addr));
insert_data(sql_str, sqldb);
}
// 处理 取出物品 功能
void deal_GET_OUT(char *buff, client_info &cli, char *name)
{
char *item = buff + 1;
char *supplier = buff + 2 + (strlen(buff + 1));
int num = *((int *)(supplier + 1 + (strlen(supplier))));
// 先查看里面有没有这么一个东西,以及这个东西是不是>=要取出的数
char sql_str[256];
char ret_msg[64] = "GET_OUT_FAILURE";
sprintf(sql_str, "select * from item_info where item_name='%s' and supplier='%s' and numb>=%d;", item, supplier, num);
// 表中有这个东西,且库存充足
if (select_data_ret_num(sql_str, sqldb) != 0)
{
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "update item_info set numb=numb-%d where item_name='%s' and supplier='%s';",
num, item, supplier);
if (insert_data(sql_str, sqldb) != -1)
{
strcpy(ret_msg, "GET_OUT_SUCESS");
}
}
// 发送 取出物品结果
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
// 存储历史记录
char operation[256] = "";
sprintf(operation, "GET_OUT_%s_%s_%d", supplier, item, num);
char now_time[64] = "";
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "insert into history (uname,operation,Obj,optime,oper_ip) values('%s','%s','%s','%s','%s');",
name, operation, item, get_time(now_time), inet_ntoa(cli.c_in.sin_addr));
insert_data(sql_str, sqldb);
// 将数量为0的物品记录清空
bzero(sql_str, sizeof(sql_str));
sprintf(sql_str, "delete from item_info where numb=0;");
insert_data(sql_str, sqldb);
}
// 处理 存放物品 功能
void deal_SAVE(char *buff, client_info &cli, char *name)
{
char *item = buff + 1;
char *supplier = buff + 2 + (strlen(buff + 1));
int num = *((int *)(supplier + 1 + (strlen(supplier))));
// 先查看里面有没有这么一个东西
char sql_str[256];
sprintf(sql_str, "select * from item_info where item_name='%s' and supplier='%s';", item, supplier);
char ret_msg[64] = "SAVE_FAILURE";
int row = select_data_ret_num(sql_str, sqldb);
bzero(sql_str, sizeof(sql_str));
// 没有这个东西,向里面插入数据
char now_time[64] = "";
if (row == 0)
{
sprintf(sql_str, "insert into item_info (item_name,supplier,numb,input_name,input_time) values('%s','%s',%d,'%s','%s');",
item, supplier, num, name, get_time(now_time));
}
// 有这个东西,更新数据
else
{
sprintf(sql_str, "update item_info set numb=numb+%d where item_name='%s' and supplier='%s';",
num, item, supplier);
}
// 是否修改存放结果
if (0 == insert_data(sql_str, sqldb))
{
strcpy(ret_msg, "SAVE_SUCESS");
}
// 发送 存放结果
if (send(cli.new_fd, &ret_msg, strlen(ret_msg), 0) < 0)
{
ERR_MSG("send");
return;
}
// 向历史记录表中插入数据
char operation[256] = "";
sprintf(operation, "SAVE_%s_%s_%d", supplier, item, num);
bzero(now_time, sizeof(now_time));
memset(sql_str, 0, sizeof(sql_str));
sprintf(sql_str, "insert into history (uname,operation,Obj,optime,oper_ip) values('%s','%s','%s','%s','%s');",
name, operation, item, get_time(now_time), inet_ntoa(cli.c_in.sin_addr));
insert_data(sql_str, sqldb);
}
// 处理登录功能
void deal_LOGIN(char *buff, client_info &cli, char *uname)
{
char *name = buff + 1;
strcpy(uname, name);
char *pwd = buff + 2 + (strlen(buff + 1));
// SQL语句
char sql_str[256];
sprintf(sql_str, "select privilege from user where uname='%s' and passwd='%s';", name, pwd);
// 查询是否有这个人
char **result = nullptr;
int row = 0;
int column = 0;
char *errmsg = nullptr;
if (sqlite3_get_table(sqldb, sql_str, &result, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_get_table error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), sqlite3_errmsg(sqldb), __LINE__);
return;
}
char ret[128];
// 没有这个人,登录失败,有则根据权限发回对应的字符串
if (row == 0)
{
strcpy(ret, "LOGIN_OR_SIGNIN_FAILURE");
}
else if (strcmp(result[column], "user") == 0)
{
strcpy(ret, "LOGIN_OR_SIGNIN_SUCCESS");
}
else if (strcmp(result[column], "admin") == 0)
{
strcpy(ret, "ADMIN_LOGIN_SUCESS");
}
// 容器不为空,且能够找到这个元素,那么返回登录失败,因为他正在登录
if (!signin_set.empty() && signin_set.find(name) != signin_set.end())
{
strcpy(ret, "LOGIN_OR_SIGNIN_FAILURE");
}
else
{
signin_set.insert(name);
}
// 向客户端发送消息
// 发送
if (send(cli.new_fd, &ret, strlen(ret), 0) < 0)
{
ERR_MSG("send");
return;
}
// 向历史记录表中插入数据
char operation[16] = "LOGIN";
char now_time[64] = "";
memset(sql_str, 0, sizeof(sql_str));
sprintf(sql_str, "insert into history (uname,operation,Obj,optime,oper_ip) values('%s','%s','%s','%s','%s');",
uname, operation, name, get_time(now_time), inet_ntoa(cli.c_in.sin_addr));
insert_data(sql_str, sqldb);
}
// 处理注册功能
void deal_SIGNIN(char *buff, client_info &cli)
{
char *name = buff + 1;
char *pwd = buff + 2 + (strlen(buff + 1));
char sql_str[256];
sprintf(sql_str, "select * from user where uname='%s';", name);
// 查询是否有这个人
int row = select_data_ret_num(sql_str, sqldb);
char ret[128] = "LOGIN_OR_SIGNIN_FAILURE";
// 没有这个人,进行注册,向用户表中插入数据
if (row == 0)
{
strcpy(ret, "LOGIN_OR_SIGNIN_SUCCESS");
// 向用户表中插入数据
memset(sql_str, 0, sizeof(sql_str));
char now_time[64] = "";
sprintf(sql_str, "insert into user (uname,passwd,privilege,signin_time) values('%s','%s','user','%s');", name, pwd, get_time(now_time));
insert_data(sql_str, sqldb);
}
// 发送 注册成功信号
if (send(cli.new_fd, &ret, strlen(ret), 0) < 0)
{
ERR_MSG("send");
return;
}
// 向历史记录表中插入数据
char operation[16] = "SIGIN";
char now_time[64] = "";
memset(sql_str, 0, sizeof(sql_str));
sprintf(sql_str, "insert into history (uname,operation,Obj,optime,oper_ip) values('%s','%s','%s','%s','%s');",
name, operation, name, get_time(now_time), inet_ntoa(cli.c_in.sin_addr));
insert_data(sql_str, sqldb);
}
// 获取当前时间,返回字符串
char *get_time(char *now_time)
{
time_t t;
struct tm *info = NULL;
time(&t);
info = localtime(&t);
sprintf(now_time, "%d-%02d-%02d %02d:%02d:%02d",
info->tm_year + 1900, info->tm_mon + 1, info->tm_mday,
info->tm_hour, info->tm_min, info->tm_sec);
return now_time;
}
// 插入数据
int insert_data(char *sql_str, sqlite3 *sqldb)
{
char *error_msg = NULL;
if (sqlite3_exec(sqldb, sql_str, NULL, NULL, &error_msg) != SQLITE_OK)
{
fprintf(stderr, "insert into TABLE error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), error_msg, __LINE__);
return -1;
}
return 0;
}
// 查询数据
int select_data_ret_num(char *sql_str, sqlite3 *sqldb)
{
char *error_msg = NULL;
char **pres = NULL;
int row, column;
if (sqlite3_get_table(sqldb, sql_str, &pres, &row, &column, &error_msg) != SQLITE_OK)
{
fprintf(stderr, "select_data_ret_num error : %d : %s __%d__\n",
sqlite3_errcode(sqldb), error_msg, __LINE__);
return 0;
}
return row;
}
makefile
EXE=server
CC=g++
CFLAGs=-c
FLAG+=-lsqlite3
FLAG+=-lpthread
OBJs+=main.o
OBJs+=server.o
all:$(EXE)
$(EXE):$(OBJs)
$(CC) $^ -o $@ $(FLAG)
%.o:%.cpp
$(CC) $(CFLAGs) $^ -o $@
clean:
rm *.o $(EXE)