2.11 sqlite3数据库【数据库的相关操作指令、函数】

news2025/2/22 23:28:49

 

练习:

将 epoll 服务器 客户端拿来用
客户端:写一个界面,里面有注册登录
服务器:处理注册和登录逻辑,注册的话将注册的账号密码写入数据库,登录的话查询数据库中是否存在账号,并验证密码是否正确
额外功能:客户端登录的时候,服务器向客户端发送一个验证码,只有验证码也正确的时候,才能登录成功·     

server.c 

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sqlite3.h>
#include <errno.h>
#include <time.h>

#define MAX_EVENTS 100

typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;

enum Type {
    TYPE_REGIST,
    TYPE_LOGIN,
    TYPE_CHAT
};

typedef struct Pack {
    enum Type type;
    char name[20];
    char pswd[20];
    char tarname[20];
    char text[1024];
} pack_t;

sqlite3 *db;  // 数据库指针

// 生成验证码
void generate_code(char *code, int length) {
    const char charset[] = "0123456789";
    srand(time(NULL));
    for (int i = 0; i < length; i++) {
        code[i] = charset[rand() % 10];
    }
    code[length] = '\0';
}

// 设置文件描述符非阻塞模式
void set_nonblocking(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

// 处理客户端请求
void handle_client(int client) {
    pack_t pack = {0};
    int res = read(client, &pack, sizeof(pack));
    if (res <= 0) {
        printf("客户端断开连接\n");
        close(client);
        return;
    }

    char sql[256];
    char *errmsg = NULL;

    switch (pack.type) {
        case TYPE_REGIST:
            snprintf(sql, sizeof(sql), "INSERT INTO users (name, password) VALUES ('%s', '%s');", pack.name, pack.pswd);
            if (sqlite3_exec(db, sql, 0, 0, &errmsg) != SQLITE_OK) {
                printf("注册失败: %s\n", errmsg);
                strcpy(pack.text, "注册失败,该账号可能已存在!");
                sqlite3_free(errmsg);
            } else {
                strcpy(pack.text, "注册成功!");
            }
            write(client, &pack, sizeof(pack));
            break;

        case TYPE_LOGIN: {
            snprintf(sql, sizeof(sql), "SELECT password FROM users WHERE name = '%s';", pack.name);
            sqlite3_stmt *stmt;
            if (sqlite3_prepare_v2(db, sql, -1, &stmt, 0) == SQLITE_OK) {
                if (sqlite3_step(stmt) == SQLITE_ROW) {
                    const char *db_pswd = (const char*)sqlite3_column_text(stmt, 0);
                    if (strcmp(db_pswd, pack.pswd) == 0) {
                        char code[6];
                        generate_code(code, 5);
                        snprintf(pack.text, sizeof(pack.text), "验证码:%s\n", code);
                        write(client, &pack, sizeof(pack));

                        // 等待客户端输入验证码
                        read(client, &pack, sizeof(pack));
                        if (strcmp(pack.text, code) == 0) {
                            strcpy(pack.text, "登录成功!");
                        } else {
                            strcpy(pack.text, "验证码错误,登录失败!");
                        }
                    } else {
                        strcpy(pack.text, "密码错误!");
                    }
                } else {
                    strcpy(pack.text, "账号不存在!");
                }
                sqlite3_finalize(stmt);
            }
            write(client, &pack, sizeof(pack));
            break;
        }

        case TYPE_CHAT:
            printf("收到消息: %s\n", pack.text);
            break;
    }
}

int main(int argc, const char *argv[]) {
    if (argc != 2) {
        printf("请输入端口号\n");
        return 1;
    }

    int port = atoi(argv[1]);

    // 初始化数据库
    if (sqlite3_open("users.db", &db) != SQLITE_OK) {
        printf("无法打开数据库\n");
        return 1;
    }

    const char *create_table_sql = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT UNIQUE, password TEXT);";
    char *errmsg = NULL;
    if (sqlite3_exec(db, create_table_sql, 0, 0, &errmsg) != SQLITE_OK) {
        printf("创建表失败: %s\n", errmsg);
        sqlite3_free(errmsg);
        return 1;
    }

    // 创建服务器 socket
    int server = socket(AF_INET, SOCK_STREAM, 0);
    addr_in_t addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;

    bind(server, (addr_t*)&addr, sizeof(addr));
    listen(server, 10);

    // 设置非阻塞模式
    set_nonblocking(server);

    // 创建 epoll
    int epoll_fd = epoll_create1(0);
    struct epoll_event ev, events[MAX_EVENTS];

    ev.events = EPOLLIN;
    ev.data.fd = server;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server, &ev);

    printf("服务器启动,监听端口 %d...\n", port);

    while (1) {
        int n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        for (int i = 0; i < n; i++) {
            if (events[i].data.fd == server) {
                // 处理新连接
                int client = accept(server, NULL, NULL);
                if (client < 0) {
                    perror("accept");
                    continue;
                }
                set_nonblocking(client);
                ev.events = EPOLLIN | EPOLLET;
                ev.data.fd = client;
                epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client, &ev);
                printf("新客户端连接: %d\n", client);
            } else {
                // 处理客户端请求
                handle_client(events[i].data.fd);
            }
        }
    }

    sqlite3_close(db);
    close(server);
    return 0;
}

client.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;

enum Type {
    TYPE_REGIST,
    TYPE_LOGIN,
    TYPE_CHAT
};

typedef struct Pack {
    enum Type type;
    char name[20];
    char pswd[20];
    char tarname[20];
    char text[1024];
} pack_t;

void handle_response(int client) {
    pack_t pack;
    int res = read(client, &pack, sizeof(pack));
    if (res > 0) {
        printf("服务器: %s\n", pack.text);
    }
}

int main(int argc, const char *argv[]) {
    if (argc != 2) {
        printf("输入端口号\n");
        return 1;
    }

    int port = atoi(argv[1]);
    int client = socket(AF_INET, SOCK_STREAM, 0);
    addr_in_t addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr("192.168.126.245");

    if (connect(client, (addr_t*)&addr, sizeof(addr)) == -1) {
        perror("连接失败");
        return 1;
    }

    printf("连接服务器成功!\n");

    while (1) {
        int ch;
        printf("1: 注册\n2: 登录\n3: 聊天\n0: 退出\n请选择: ");
        scanf("%d", &ch);
        while (getchar() != '\n');

        pack_t pack = {0};
        
        switch (ch) {
            case 1:
                printf("输入账号: ");
                scanf("%s", pack.name);
                while (getchar() != '\n');
                printf("输入密码: ");
                scanf("%s", pack.pswd);
                while (getchar() != '\n');
                pack.type = TYPE_REGIST;
                write(client, &pack, sizeof(pack));
                handle_response(client);
                break;

            case 2:
                printf("输入账号: ");
                scanf("%s", pack.name);
                while (getchar() != '\n');
                printf("输入密码: ");
                scanf("%s", pack.pswd);
                while (getchar() != '\n');
                pack.type = TYPE_LOGIN;
                write(client, &pack, sizeof(pack));

                handle_response(client); // 服务器发送验证码

                printf("输入验证码: ");
                scanf("%s", pack.text);
                while (getchar() != '\n');
                write(client, &pack, sizeof(pack));
                
                handle_response(client); // 登录成功 or 失败
                break;

            case 3:
                printf("输入聊天对象: ");
                scanf("%s", pack.tarname);
                while (getchar() != '\n');
                printf("输入消息: ");
                fgets(pack.text, sizeof(pack.text), stdin);
                pack.text[strcspn(pack.text, "\n")] = '\0'; // 去除换行符
                pack.type = TYPE_CHAT;
                write(client, &pack, sizeof(pack));
                handle_response(client);
                break;

            case 0:
                close(client);
                return 0;

            default:
                printf("无效选项\n");
        }
    }

    return 0;
}

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

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

相关文章

相得益彰,Mendix AI connector 秒连DeepSeek ,实现研发制造域场景

在当今快速发展的科技领域&#xff0c;低代码一体化平台已成为企业数字化转型的关键工具&#xff0c;同时&#xff0c;大型语言模型&#xff08;LLM&#xff09;如 DeepSeek 在自动生成代码和提供智能建议方面表现出色。 Mendix 于近期发布的 GenAI 万能连接器&#xff0c;目前…

同为科技智能PDU助力Deepseek人工智能和数据交互的快速发展

1 2025开年&#xff0c;人工智能领域迎来了一场前所未有的变革。Deepseek成为代表“东方力量”的开年王炸&#xff0c;不仅在国内掀起了技术热潮&#xff0c;并且在全球范围内引起了高度关注。Deepseek以颠覆性技术突破和现象级应用场景席卷全球&#xff0c;这不仅重塑了产业格…

.NET Web-静态文件访问目录浏览

一、Web根目录访问 创建wwwroot文件夹app.UseStaticFiles(); // 启⽤静态⽂件中间件url/路径 进行访问 二、Web根目录之外的文件 app.UseStaticFiles(new StaticFileOptions {FileProvider new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath,&qu…

【CubeMX+STM32】SD卡 U盘文件系统 USB+FATFS

本篇&#xff0c;将使用CubeMXKeil, 创建一个 USBTF卡存储FatFS 的虚拟U盘读写工程。 目录 一、简述 二、CubeMX 配置 SDIO DMA FatFs USB 三、Keil 编辑代码 四、实验效果 串口助手&#xff0c;实现效果&#xff1a; U盘&#xff0c;识别效果&#xff1a; 一、简述 上…

node.js+兰空图床实现随机图

之前博客一直用的公共的随机图API&#xff0c;虽然图片的质量都挺不错的&#xff0c;但是稳定性都比较一般&#xff0c;遂打算使用之前部署的兰空图床&#xff0c;自己弄一个随机图 本文章服务器操作基于雨云——新一代云服务提供商的云服务器进行操作&#xff0c;有兴趣的话可…

DeepSeek AI 满血版功能集成到WPS或Microsoft Office中

DeepSeek AI集成到 WPS或Microsoft Office中, 由于deepseek被攻击或者非常繁忙导致超时的服务器&#xff0c;所以可以用硅基流动部署的DeepSeek 。当然用官网的也可以。 使用 OfficeAI 插件集成(wps为例)&#xff1a; 下载并安装 OfficeAI 插件&#xff1a;从可靠的软件下载平台…

微服务SpringCloud Alibaba组件nacos教程(一)【详解naocs基础使用、服务中心配置、集群配置,附有案例+示例代码】

一.Nacos教程 文章目录 一.Nacos教程1.1 Nacos简介1.2 nacos基本使用直接下载打包服务源码方式启动 1.3 创建nacos客服端1.4 nacos集群配置1.5 nacos配置中心 1.1 Nacos简介 nacos是spring cloud alibaba生态中非常重要的一个组件&#xff0c;它有两个作用&#xff1a; 1:注册…

Kotlin 扩展函数与内联函数

Kotlin扩展函数 Kotlin 的扩展函数是 Kotlin 中非常强大且实用的功能。它允许你为现有的类添加新的方法&#xff0c;而不需要修改其源代码。这意味着你可以在已有的类上“扩展”新的功能&#xff0c;使用起来就像是原本就存在这些方法一样。 扩展函数的基本语法 fun 类名.方…

企业文件防泄密软件哪个好?

在企业文件防泄密软件领域&#xff0c;天锐绿盾和中科数安都是备受认可的品牌&#xff0c;它们各自具有独特的特点和优势。 以下是对这两款软件的详细比较&#xff1a; 天锐绿盾 功能特点 集成性强&#xff1a;集成了文件加密、数据泄露防护DLP、终端安全管理、行为审计等数据安…

【Qt 常用控件】多元素控件(QListWidget、QTableWidgt、QTreeWidget)

**View和**Widget的区别&#xff1f; **View的实现更底层&#xff0c;**Widget是基于**View封装实现的更易用的类型。 **View使用MVC结构 MVC是软件开发中 经典的 软件结构 组织形式&#xff0c;软件设计模式。 M&#xff08;model&#xff09;模型。管理应用程序的核心数据和…

VS2022中.Net Api + Vue 从创建到发布到IIS

VS2022中.Net Api Vue 从创建到发布到IIS 前言一、先决条件二、创建项目三、运行项目四、增加API五、发布到IIS六、设置Vue的发布 前言 最近从VS2019 升级到了VS2022,终于可以使用官方的.Net Vue 组合了,但是使用过程中还是有很多问题,这里记录一下. 一、先决条件 Visual …

Windows 11 搭建私有知识库(docker、dify、deepseek、ollama)

一、操作系统信息 版本 Windows 11 家庭中文版 版本号 23H2 安装日期 ‎2023/‎8/‎21 操作系统版本 22631.4460二、搭建思路 ollama拉取deepseek、bge-m3模型docker拉取dify的镜像dify链接ollama使用模型&#xff0c;并上传文件搭建知识库&#xff0c;创建应用 三、搭建步骤…

安装OpenJDK21(linux、macos)

文章目录 安装OpenJDK21java21linux下安装配置mac下安装 安装OpenJDK21 java21 封神&#xff01;Java 21正式发布了&#xff0c;迎来了史诗级新特性&#xff0c;堪称版本最强&#xff01;&#xff01;&#xff01; 视频链接&#xff1a;https://www.bilibili.com/video/BV1E8…

变分边界详解

起因 当时看VAE论文时有这么一段&#xff0c;但是看完直接一头雾水&#xff0c;这都那跟哪&#xff0c;第一个公式咋做的变换就变出那么一堆。网上搜了很多博客都语焉不详&#xff0c;只好自己来写一篇&#xff0c;希望能解答后来人的疑惑。 公式1 参考文章&#xff1a;证据…

Next.js 15【实用教程】2025最新版

官网 https://nextjs.org/docs/app/getting-started Next.js 简介 Next.js 由 Vercel 开发和维护&#xff0c;旨在解决单页应用&#xff08;SPA&#xff09;和多页应用&#xff08;MPA&#xff09;在性能和 SEO 上的不足。 核心特性 服务端渲染&#xff08;SSR&#xff09;--…

2025-02-13 学习记录--C/C++-PTA 7-17 爬动的蠕虫

一、题目描述 ⭐️ 二、代码&#xff08;C语言&#xff09;⭐️ #include <stdio.h>int main() {int N, U, D; // N: 井的总高度&#xff0c;U: 每分钟向上爬的高度&#xff0c;D: 每分钟滑下的高度int height 0; // 蠕虫当前的高度int minute 0; // 蠕虫爬行的时间sc…

Elasticsearch+Logstash+Kibana可视化集群部署

文章目录 1.组件介绍简述2.集群规划3.Es组件部署4.Logstash组件部署5.Kibana组件部署6.Kibana的基础使用 1.组件介绍简述 Elasticsearch&#xff1a;开源实时分布式搜索和分析引擎&#xff0c;支持大规模数据存储和高吞吐量&#xff0c;提供丰富的搜索功能和可扩展性。 Logsta…

DeepSeek+Excel 效率翻倍

2025年初&#xff0c;DeepSeek以惊人的效率突破技术壁垒&#xff0c;用极低的成本实现了与行业顶尖AI相媲美的性能&#xff0c;瞬间成为全球科技领域的热门话题。 那么AI工具的普及将如何改变我们的工作方式&#xff1f;Excel会被取代吗&#xff1f; 今天&#xff0c;珠珠带你…

将Sqlite3数据库挂在内存上处理

创作灵感&#xff1a;最近把小学生的口算题从2位数改到3位数&#xff0c;100以内四则运算练习&#xff08;千纬数学&#xff09;再次更新&#xff0c;选取难题-CSDN博客要不断刷题目&#xff0c;以前100以内的加减乘除也是这样刷出来的&#xff0c;代码如下&#xff1a; impor…

electron.vite 项目创建以及better-sqlite3数据库使用

1.安装electron.vite npm create quick-start/electronlatest中文官网&#xff1a;https://cn.electron-vite.org/ 2. 安装项目依赖 npm i3.修改 electron-builder 配置文件 appId: com.electron.app productName: text33 directories:buildResources: build files:- !**/.v…