嵌入式养成计划-48----QT--信息管理系统:百川仓储管理

一百二十二、信息管理系统:百川仓储管理

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//  因为前面创建流式套接字用的是 IPv4server_in.sin_port = htons(SERVER_PORT);          //  指定端口号server_in.sin_addr.s_addr = inet_addr(SERVER_IP); //  绑定本机IPif (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 ");//  如果 或物品, 或供应商,有任何一个存在,则加上whereif (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 ");//  如果 用户名, 或物品,有任何一个存在,则加上whereif (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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/137560.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Semantic-Guided Zero-Shot Learning for Low-Light ImageVideo Enhancement

论文阅读之无监督低光照图像增强 Semantic-Guided Zero-Shot Learning for Low-Light Image/Video Enhancement 代码&#xff1a; https://github.com/ShenZheng2000/SemantiGuided-Low-Light-Image-Enhancement 在低光条件下增加亮度的一个可行方法是使用更高的ISO或更长时间…

仿mudou库one thread one loop式并发服务器

目录 1.实现目标 2.HTTP服务器 实现高性能服务器-Reactor模型 模块划分 SERVER模块&#xff1a; HTTP协议模块&#xff1a; 3.项目中的子功能 秒级定时任务实现 时间轮实现 正则库的简单使用 通⽤类型any类型的实现 4.SERVER服务器实现 日志宏的封装 缓冲区Buffer…

简单漂亮的登录页面

效果图 说明 开发环境&#xff1a;vue3&#xff0c;sass 代码 <template><div class"container"><div class"card-container"><div class"card-left"><span><h1>Dashboard</h1><p>Lorem ip…

HTTP 协议详解-上(Fiddler 抓包演示)

文章目录 HTTP 协议HTTP 协议的工作过程HTTP 请求 (Request)认识URL关于 URL encode认识 "方法" (method)GET 方法POST 方法其他方法请求 "报头" (header)请求 "正文" (body) HTTP 响应详解状态码响应 "报头" (header) HTTP 协议 HTT…

【编程语言发展史】Unity开发语言的历史发展

Unity开发前期版本时&#xff0c;使用的是一种名为UnityScript的类似JavaScript的语言。然而&#xff0c;随着时间的推移&#xff0c;开发者社区大多数人都倾向于使用C#进行开发&#xff0c;Unity决定将重点放在C#上&#xff0c;因为C#具有更强大的生态系统、更好的性能和更广泛…

Spring Boot 3.0正式发布及新特性解读

目录 【1】Spring Boot 3.0正式发布及新特性依赖调整升级的关键变更支持 GraalVM 原生镜像 Spring Boot 最新支持版本Spring Boo 版本版本 3.1.5前置系统清单三方包升级 Ref 个人主页: 【⭐️个人主页】 需要您的【&#x1f496; 点赞关注】支持 &#x1f4af; 【1】Spring Boo…

月销破30万辆后,比亚迪整了波大的

最近乘联会公布了 2023 年 10 月新能源乘用车厂商销量榜单。 其中最为亮眼犹如鹤立鸡群的榜首&#xff0c;没错依然是我们熟悉的那个迪子&#xff01; 单月销量超 30 万辆&#xff0c;相较去年同期暴涨 38.4%&#xff0c;创下了比亚迪有史以来新高。 同时也成为了国内首个月销…

element-ui的form校验失败

数值与字符串混淆 数值 <el-input type"number" v-model.number"form.averageFruitWeight" placeholder"请输入平均单果重"/>字符串 fruitDevelopmentStage: [{pattern: ^[-\\]?([0-9]\\.?)?[0-9]$, message: 输入必须为数字, trigge…

AD教程 (十一)封装的统一管理

AD教程 (十一)封装的统一管理 PCB封装添加 一个一个手动添加&#xff0c;效率太低&#xff0c;不建议使用 使用封装管理器快速添加&#xff0c;根据BOM表&#xff08;元器件清单&#xff09;&#xff0c;修改PCB封装 点击工具&#xff0c;选择封装管理器&#xff0c;进入封装…

耳机放大器的作用?HT97180 耳机放大器的作用又是什么?

耳机放大器是一种用于增强耳机音频信号的设备&#xff0c;它在提供更大音量、更好音质方面起到重要作用。它可以为耳机用户提供更好的音频体验&#xff0c;特别是对于高阻抗耳机和音频爱好者来说非常有用。 而HT97180为差分输入、可直接输出的耳机放大器。4.2V供电时&#xff0…

游戏缺失d3dx9_39.dll的5个修复方法,深度解析d3dx9_39.dll文件的作用

在当今的数字化时代&#xff0c;电子游戏已经成为了人们休闲娱乐的重要方式之一。然而&#xff0c;对于许多玩家来说&#xff0c;他们在享受游戏带来的乐趣的同时&#xff0c;也可能会遇到各种各样的问题&#xff0c;其中最常见的就是游戏无法正常运行。而这些问题中&#xff0…

【学术综述】-如何写出一篇好综述-写好综述要注意的问题

文章目录 1.前置1.1 SSD 的结构1.2 FTL的架构和作用 2 动机-why&#xff1f;3 做了什么【做了哪些方面的survey】&#xff1f;4 背景知识【上下文】5 研究的问题6 每个问题对应的解决方案 从昨天晚上【2023.11.09 22:00】到今天22:29的&#xff0c;花了一天的时间在读这篇surve…

Netty入门指南之NIO 网络编程

作者简介&#xff1a;☕️大家好&#xff0c;我是Aomsir&#xff0c;一个爱折腾的开发者&#xff01; 个人主页&#xff1a;Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏-CSDN博客 当前专栏&#xff1a;Netty应用专栏_Aomsir的博客-CSDN博客 文章目录 参考文献前言基础扫…

找不到模块“./App.vue”或其相应的类型声明。ts(2307)

先看报错信息&#xff1a; 这是我们初始创建是就自带的&#xff0c;怎么会错误呢&#xff0c;实际上是因为未定义 .vue文件的类型&#xff0c;导致 ts 无法解析其类型&#xff0c;在env.d.ts中定义后即可解决。 对于我们初学者来说&#xff0c;刚刚按照视频来创建的项目怎么啥…

【Delphi】Android 开发HTTP请求出错解决方案

目录 一、故障现象 二、原因及解决方案 一、故障现象 在android内建的WebBrowser浏览器中通过http访问一个网站&#xff08;注意不是https&#xff09;&#xff0c;出现如下错误提示&#xff1a; 在使用ntfy的时候&#xff0c;访问http定义的服务器地址&#xff08;注意不是…

【ATTCK】MITRE ATTCK 设计与哲学

MITRE ATT&CK™:设计与哲学 来源&#xff1a;MITRE ATT&CK™: Design and Philosophy 摘要 MITRE ATT&CK知识库描述了网络对手的行为&#xff0c;并为攻击和防御提供了一个通用的分类。它已成为跨许多网络安全领域的一个有用工具&#xff0c;用于传递威胁情报&…

SSM之spring注解式缓存redis->redis整合,redis的注解式开发及应用场景,redis的击穿穿透雪崩

redis整合redis的注解式开发及应用场景redis的击穿穿透雪崩 1.redis整合 mysql整合 pom配置&#xff1b; String-fmybatis.xml --> mybatis.cfg.xml: 包扫描&#xff1b; 注册了一个jdbc.properties(url/password/username/...)&#xff1b; 配置数据源&#xff08;数据库连…

docker部署redis6

前言&#xff1a;在离线服务器上&#xff08;无联网&#xff09;&#xff0c;部署redis的方式&#xff0c;采用docker是比较方便的。下面将描述如何使用docker部署单机版redis 环境&#xff1a;centos 7 redis&#xff1a;6.2.14 docker&#xff1a;20.10.9 1.下载 redis 镜像…

卡牌游戏类型定制开发微信卡牌小程序游戏

卡牌类型的游戏开发具有一些独特的特点和挑战&#xff0c;以下是一些主要的特点&#xff1a; 卡牌设计和平衡&#xff1a;卡牌游戏的核心是卡牌设计和平衡。开发团队需要设计各种卡牌&#xff0c;确保它们在游戏中相互平衡&#xff0c;以便提供有趣的游戏体验。卡牌的特性、效…

服务器数据恢复—误还原虚拟机快照后如何恢复之前的数据?

服务器数据恢复环境&#xff1a; vmfs文件系统&#xff0c;存放的是SqlServer数据库及其他办公文件。 服务器故障&#xff1a; 工作人员误操作还原快照&#xff0c;导致了SqlServer数据库数据丢失。 服务器数据恢复过程&#xff1a; 1、拿到故障服务器的所有磁盘后&#xff0c…