嵌入式养成计划-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.rhkb.cn/news/188631.html

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

相关文章

学习c#的第五天

目录 C# 运算符 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 其他运算符 C# 中的运算符优先级 C# 运算符 算术运算符 下表显示了 C# 支持的所有算术运算符。假设变量 A 的值为 10&#xff0c;变量 B 的值为 20&#xff0c;则&#xff1a; 运算符描述实例…

JVM在线分析-解决问题的工具一(jinfo,jmap,jstack)

1. jinfo (base) PS C:\Users\zishi\Desktop> jinfo Usage:jinfo <option> <pid>(to connect to a running process)where <option> is one of:-flag <name> to print the value of the named VM flag #输出对应名称的参数-flag [|-]<n…

ElasticSearch7.x - HTTP 操作 - 文档操作

创建文档(添加数据) 索引已经创建好了,接下来我们来创建文档,并添加数据。这里的文档可以类比为关系型数 据库中的表数据,添加的数据格式为 JSON 格式 向 ES 服务器发 POST 请求 :http://192.168.254.101:9200/shopping/_doc 请求体内容为: {"title":"小…

【Python 千题 —— 基础篇】账号登录

题目描述 题目描述 简易登录系统。你的账号密码分别是 “student”&#xff0c;“123456”&#xff1b;请使用 if-else 设计一个简易登录系统&#xff0c;输入账号密码。登陆成功输出 “Welcome !”&#xff0c;登录失败输出 “Login failed !” 输入描述 输入账号和密码。…

idea配置tomcat参数,防止nvarchar保存韩文、俄文、日文等乱码

描述下我的场景&#xff1a; 数据库服务器在远程机器上&#xff0c;数据库使用的Oracle&#xff0c;字符集是ZHS16GBK&#xff0c;但保存韩文、俄文、日文等字段A的数据类型是nvarchar(120)&#xff0c;而nvarchar使用的是Unicode 编码&#xff0c;有点乱。。 遇到的问题&…

【机器学习范式】监督学习,无监督学习,强化学习, 半监督学习,自监督学习,迁移学习,对比分析+详解与示例代码

目录 1. 监督学习 (Supervised Learning): 2. 无监督学习 (Unsupervised Learning): 3. 强化学习 (Reinforcement Learning): 4. 半监督学习 (Semi-Supervised Learning): 5. 自监督学习 (Self-Supervised Learning): 6. 迁移学习 (Transfer Learning): 7 机器学习范式应…

AI:67-基于深度学习的脱机手写汉字识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…

『Linux升级路』基础开发工具——vim篇

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;Linux &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、vim的基本概念 &#x1f4d2;1.1命令模式 &#x1f4d2;1.2插入模式 &…

dcat admin 各种问题

样式问题 如何根据条件给表格数据栏添加背景色 use Illuminate\Support\Collection;protected function grid(){return Grid::make(new BookArticle(), function (Grid $grid) {... 其他代码// Collection的完整路径&#xff1a;Illuminate\Support\Collection;$grid->row…

Spark的执行计划

Spark 3.0 大版本发布&#xff0c;Spark SQL 的优化占比将近 50%。Spark SQL 取代 Spark Core&#xff0c;成为新一代的引擎内核&#xff0c;所有其他子框架如 Mllib、Streaming 和 Graph&#xff0c;都可以共享 Spark SQL 的性能优化&#xff0c;都能从 Spark 社区对于 Spark …

笔记:AI量化策略开发流程-基于BigQuant平台(一)

从本文开始&#xff0c;按照AI策略开发的完整流程&#xff08;共七步&#xff09;&#xff0c;上手在BigQuant平台上快速构建AI策略。本文首先介绍如何使用证券代码模块指定股票范围和数据起止日期。重要的事情说三遍&#xff1a;模块的输入端口有提示需要连线的上游数据类型&a…

魔搭社区LLM模型部署实践, 以ChatGLM3为例(一)

魔搭社区LLM模型部署实践&#xff0c; 以ChatGLM3为 例 本文以ChatGLM3-6B为例&#xff0c; 主要介绍在魔搭社区如何部署LLM&#xff0c; 主要包括如下内容&#xff1a; ● SwingDeploy - 云端部署&#xff0c; 实现零代码一键部署 ● 多端部署 - MAC个人笔记本&#xff0c;…

快速入门安装及使用git与svn的区别常用命令

一、导言 1、什么是svn&#xff1f; SVN是Subversion的简称&#xff0c;是一个集中式版本控制系统。与Git不同&#xff0c;SVN没有分布式的特性。在SVN中&#xff0c;项目的代码仓库位于服务器上&#xff0c;团队成员通过向服务器提交和获取代码来实现版本控制。SVN记录了每个…

Leetcode刷题详解—— 目标和

1. 题目链接&#xff1a;494. 目标和 2. 题目描述&#xff1a; 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 &#xff1a; 例如&#xff0c;nums [2, 1] &#xff0c;可…

时间序列预测实战(十二)DLinear模型实现滚动长期预测并可视化预测结果

官方论文地址->官方论文地址 官方代码地址->官方代码地址 个人修改代码->个人修改的代码已经上传CSDN免费下载 一、本文介绍 本文给大家带来是DLinear模型&#xff0c;DLinear是一种用于时间序列预测&#xff08;TSF&#xff09;的简单架构&#xff0c;DLinear的核…

Ansible自动化运维工具及模块

目录 一、Ansible 1.ansible简介 2、ansible的特性 二、ansible的部署 1&#xff09;管理端安装ansible 2&#xff09;配置主机清单 3&#xff09;配置密钥对验证 三、ansible命令块模块 1&#xff09;command模块 2&#xff09;shell模块 3&#xff09;cron模块 4)…

Jdk 1.8 for mac 详细安装教程(含版本切换)

Jdk 1.8 for mac 详细安装教程&#xff08;含版本切换&#xff09; 官网下载链接 https://www.oracle.com/cn/java/technologies/downloads/#java8-mac 一、选择我们需要安装的jdk版本&#xff0c;这里以jdk8为例&#xff0c;下载 macOS 版本&#xff0c;M芯片下载ARM64版本…

数据结构之双向链表

目录 引言 链表的分类 双向链表的结构 双向链表的实现 定义 创建新节点 初始化 打印 尾插 头插 判断链表是否为空 尾删 头删 查找与修改 指定插入 指定删除 销毁 顺序表和双向链表的优缺点分析 源代码 dlist.h dlist.c test.c 引言 数据结构…

网络通信TCP、UDP详解

目录 IP 和端口 网络传输中的 2 个对象&#xff1a;server 和 client 两种传输方式&#xff1a;TCP/UDP TCP 和 UDP 原理上的区别 为何存在 UDP 协议 TCP/UDP 网络通信大概交互图 IP 和端口 所有的数据传输&#xff0c;都有三个要素 &#xff1a;源、目的、长度。 怎么表…