嵌入式养成计划-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
                                                      //  因为前面创建流式套接字用的是 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)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CodeWhisperer 的正确使用

1、重点&#xff1a; 重点1&#xff1a; 推出 Amazon Bedrock。这项新服务允许用户通过 API 访问来自 AI21 Labs、Anthropic、Stability AI 和亚马逊的基础模型。&#xff08;Anthropic 就是之前跟 ChatGPT 掰手腕的 Claude 的模型。Stability AI 就是 Stable Diffusion 背后的…

IP 地址冲突检测工具

IP 冲突是一个术语&#xff0c;用于表示同一网络或子网中尝试使用相同 IP 地址的两个或多个设备的状态&#xff0c;这可能会导致发往特定主机的通信与其他主机混淆&#xff0c;因为两者都使用相同的 IP&#xff0c;为了避免这种情况&#xff0c;某些主机在发生 IP 冲突时会失去…

MySQL中的多列子查询

-- 多列子查询 -- 如何查询与WOARD 的部门和岗位完全相同的所有雇员(并且不含smith本人) -- (字段1&#xff0c;字段2...) (select 字段1&#xff0c;字段2 from ...) -- 分析&#xff1a; 1. 得到smith的部门和岗位 SELECT deptno,job FROM empWHERE ename WARD; -- 2.使…

大数据-玩转数据-Flume

一、Flume简介 Flume提供一个分布式的,可靠的,对大数据量的日志进行高效收集、聚集、移动的服务,Flume只能在Unix环境下运行。Flume基于流式架构,容错性强,也很灵活简单。Flume、Kafka用来实时进行数据收集,Spark、Flink用来实时处理数据,impala用来实时查询。二、Flume…

挑战100天 AI In LeetCode Day05(热题+面试经典150题)

挑战100天 AI In LeetCode Day05&#xff08;热题面试经典150题&#xff09; 一、LeetCode介绍二、LeetCode 热题 HOT 100-72.1 题目2.2 题解 三、面试经典 150 题-73.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站&#xff0c;提供各种算法和数据结构的题目&am…

JVM GC 垃圾收集器

文章目录 System.gc()内存溢出&#xff08;OOM&#xff09;OOM 的原因 内存泄漏垃圾回收的并行与并发安全点与安全区域 Java 中的引用分类强引用&#xff08;Strong Reference&#xff09;软引用&#xff08;Soft Reference&#xff09;弱引用&#xff08;Weak Reference&#…

基于SSM的小区物业管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

Flink SQL Regular Join 、Interval Join、Temporal Join、Lookup Join 详解

Flink ⽀持⾮常多的数据 Join ⽅式&#xff0c;主要包括以下三种&#xff1a; 动态表&#xff08;流&#xff09;与动态表&#xff08;流&#xff09;的 Join动态表&#xff08;流&#xff09;与外部维表&#xff08;⽐如 Redis&#xff09;的 Join动态表字段的列转⾏&#xf…

Linux 入门

Linux 入门 1&#xff1a;linux 用户 root 用户 &#xff1a;也叫超级用户&#xff0c;UID0&#xff0c;其权限最高。系统用户&#xff1a;也叫虚拟用户&#xff0c;UID 1-999普通用户: UID1000-60000, 可以登录系统,操作自己目录下的文件. 1.1:用户操作命令 切换用户: su …

STM32外部中断大问题

问题&#xff1a;一直进入中断&#xff0c;没有触发信号&#xff0c;也一直进入。 描述&#xff1a;开PA0为外部中断&#xff0c;刚刚很好&#xff0c;一个触发信号一个中断&#xff0c;中断函数没有丢&#xff0c;也没有抢跑&#xff0c;开PA1为外部中断也是&#xff0c;都很好…

nfs配置

1.NFS介绍 NFS就是Network File System的缩写&#xff0c;它最大的功能就是可以通过网络&#xff0c;让不同的机器、不同的操 作系统可以共享彼此的文件。 NFS服务器可以让PC将网络中的NFS服务器共享的目录挂载到本地端的文 件系统中&#xff0c;而在本地端的系统中来看&#…

C++初阶 | [二] 类和对象(上)

摘要&#xff1a;class&#xff0c;成员函数&#xff0c;成员变量&#xff0c;类的大小&#xff0c;this 指针 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象…

CSS 网页布局

网页布局有很多种方式&#xff0c;一般分为以下几个部分&#xff1a;头部区域、菜单导航区域、内容区域、底部区域&#xff1a; 1&#xff09;、头部区域位于整个网页的顶部&#xff0c;一般用于设置网页的标题或者网页的logo。 <style> body { margin: 0; } /* 头部样…

【Redis】list常用命令内部编码使用场景

文章目录 前置知识列表类型的特点 命令LPUSHLPUSHXRPUSHRPUSHXLRANGELPOPRPOPLINDEXLREMLINSERTLTRIMLSETLLEN 阻塞版本命令BLPOPBRPOP 命令总结内部编码测试内部编码 使用场景消息队列分频道的消息队列 模拟栈和队列 前置知识 列表类型是⽤来存储多个有序的字符串&#xff0c…

软件测试|Monkey基本参数介绍

说到android移动端稳定性测试&#xff0c;大家通常会想到android系统自动Monkey小猴子&#xff0c;通过Monkey命令模拟用户触摸点击屏幕、滑动、系统按键等操作来对设备上的app进行压力测试&#xff0c;来测试应用的稳定性和健壮性。 下面就说说monkey常用参数的用法~~ 1、-h…

Spring笔记(二)(黑马)(AOP面向切面编程)

01、AOP 简介 1.1 AOP的概念 AOP&#xff0c;Aspect Oriented Programming&#xff0c;面向切面编程&#xff0c;是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象&#xff0c;一个对象包括静态的属性信息&#xff0c;包括动态的方法信息等。而AOP是横向的对不同事物的…

spdk用户态块层详解

先通过回顾内核态的通用块层来详细介绍SPDK通用块层&#xff0c;包括通用块层的架构、核心数据结构、数据流方面的考量等。最后描述基于通用块层之上的两个特性&#xff1a;一是逻辑卷的支持&#xff0c;基于通用块设备的Blobstore和各种逻辑卷的特性&#xff0c;精简配置&…

C# OpenCvSharp 去除文字中的线条

效果 中间过程效果 项目 代码 using OpenCvSharp; using System; using System.Drawing; using System.Windows.Forms; using static System.Net.Mime.MediaTypeNames;namespace OpenCvSharp_Demo {public partial class frmMain : Form{public frmMain(){InitializeComponent…

Spring面试题:(四)Spring Bean生命周期

Bean生命周期的阶段 实例化初始化完成销毁 IoC容器实例化Bean的流程 Bean定义 Bean工厂处理 反射实例化Bean 初始化 完成存储到单例池 Bean生命周期 Bean初始化话过程 属性填充aware接口BeanPostProcessor前置处理InitialzingBean接口初始化方法自定义init方法BeanPost…

Oracle(15)Managing Users

目录 一、基础知识 1、Users and Security 用户和安全 2、Database Schema 3、Checklist for Creating Users创建用户步骤 二、基础操作 1、创建一个用户 2、OS Authentication 操作系统身份验证 3、Dropping a User 删除用户 4、Getting User Information 获取用户信…