网编数据库小练习

搭建服务器客户端,要求 服务器使用 epoll 模型 客户端使用多线程 服务器打开数据库,表单格式如下 name text primary key       pswd text not null 客户端做一个简单的界面:

1:注册

2:登录

无论注册还是登录,都需要输入账号密码后,发送给服务器 服务器接受到账号密码之后,判断一下是注册还是登录

如果是注册: 将账号密码写入数据库 如果写入失败,则通知客户端 "该账号已存在"

如果写入成功,则通知客户端 "注册成功"

如果是登录 判断账号是否存在 如果不存在,则通知客户端 "该账号不存在"

如果存在,则继续比对密码 如果密码错误,则通知客户端 "密码错误"

如果密码正确,则通知客户端 "登录成功"

client代码段:#include <25051head.h>
#include <sqlite3.h>
enum Type{TYPE_REGIST,TYPE_LOGIN
};enum Err{SUCCESS,ERR_NAME,ERR_PSWD
};typedef struct Pack{enum Type type;enum Err err;char name[16];char pswd[16];
}pack_t;pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;void* pthread_func(void* arg)
{pthread_mutex_lock(&mutex2);int client = *(int*)arg;pack_t pack = {0};while(1){int n = read(client,&pack,sizeof(pack));if (n <= 0){printf("服务器断开连接\n");break;}switch(pack.type){case TYPE_REGIST:{if (pack.err == SUCCESS){printf("\n账号创建成功!\n\n");}else{printf("\n账号创建失败!\n\n");}pthread_mutex_unlock(&mutex1);break;}case TYPE_LOGIN:{if (pack.err == SUCCESS){printf("\n登录成功!\n\n");}else if (pack.err == ERR_NAME){printf("\n请检查用户名是否输入有误!\n\n");}else{printf("\n请检查密码是否输入有误!\n\n");}pthread_mutex_unlock(&mutex1);break;}}}return NULL;
}int main(int argc, const char *argv[])
{if (argc < 2){printf("请输入端口号:");return 1;}short port = atoi(argv[1]);int client = socket(AF_INET,SOCK_STREAM,0);struct sockaddr_in addr4 = {0};addr4.sin_family = AF_INET;addr4.sin_port = htons(port);addr4.sin_addr.s_addr = inet_addr("127.0.0.1");connect(client,(struct sockaddr*)&addr4,sizeof(addr4));pthread_t tid;int *client_ptr = malloc(sizeof(int));*client_ptr = client;pthread_create(&tid, 0, pthread_func, client_ptr);int ch = 0;pthread_mutex_lock(&mutex2);while(1){pthread_mutex_lock(&mutex1);pack_t pack = {0};printf("====菜单====\n");printf("1.注册\n");printf("2.登录\n");printf("请输入你的选择:");scanf("%d",&ch);getchar();putchar('\n');switch(ch){case 1:{printf("请设置您的账号:");scanf("%s",pack.name);getchar();printf("请设置您的密码:");scanf("%s",pack.pswd);getchar();pack.type = TYPE_REGIST;write(client,&pack,sizeof(pack));break;}case 2:{printf("请输入账号:");scanf("%s",pack.name);getchar();printf("请输入密码:");scanf("%s",pack.pswd);getchar();pack.type = TYPE_LOGIN;write(client,&pack,sizeof(pack));sleep(1);break;}default:{printf("输入错误,请重新输入!\n");break;}}pthread_mutex_unlock(&mutex2);}return 0;
}
server服务器端代码:(epoll模型)#include <25051head.h>
#include <sqlite3.h>
enum Type{TYPE_REGIST,TYPE_LOGIN
};enum Err{SUCCESS,ERR_NAME,ERR_PSWD
};typedef struct Pack{enum Type type;enum Err err;char name[16];char pswd[16];
}pack_t;void regist(pack_t* pack,int client,sqlite3* db)
{sqlite3_stmt* stmt = NULL;char* sql = "insert into users(name,pswd) values(?,?)";int res = sqlite3_prepare_v2(db,sql,-1,&stmt,NULL);if (res != SQLITE_OK){pack->err = ERR_NAME;}sqlite3_bind_text(stmt,1,pack->name,-1,NULL);sqlite3_bind_text(stmt,2,pack->pswd,-1,NULL);res = sqlite3_step(stmt);if(res == SQLITE_DONE){pack->err = SUCCESS;}else{pack->err = ERR_NAME;}//pack.type = TYPE_REGIST;sqlite3_finalize(stmt);write(client,pack,sizeof(*pack));
}void login(pack_t* pack,int client,sqlite3* db)
{sqlite3_stmt* stmt = NULL;char* sql = "select pswd from users where name = ?";int res = sqlite3_prepare_v2(db,sql,-1,&stmt,NULL);if (res != SQLITE_OK){pack->err = ERR_NAME;}sqlite3_bind_text(stmt,1,pack->name,-1,NULL);res = sqlite3_step(stmt);if(res == SQLITE_DONE){pack->err = ERR_NAME;	}else if (res == SQLITE_ROW){const char* db_pswd = sqlite3_column_text(stmt,0);if(strcmp(db_pswd,pack->pswd) == 0){pack->err = SUCCESS;}else{pack->err = ERR_PSWD;}}sqlite3_finalize(stmt);write(client,pack,sizeof(*pack));
}int main(int argc, const char *argv[])
{if(argc < 2){printf("请输入端口号\n");return 1;}short port = atoi(argv[1]);// "abc123" -> 0int server = socket(AF_INET,SOCK_STREAM,0);struct sockaddr_in addr = {0};addr.sin_family = AF_INET;	addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr("0.0.0.0");if(bind(server,(struct sockaddr*)&addr,sizeof(addr)) == -1){perror("bind");return 1;}listen(server,10);sqlite3* db = NULL;sqlite3_open("./lx.db",&db);int epfd = epoll_create1(EPOLL_CLOEXEC);struct epoll_event epoll_stdin = {.events = EPOLLIN , .data.fd = 0};struct epoll_event epoll_server = {.events = EPOLLIN , .data.fd = server};epoll_ctl(epfd,EPOLL_CTL_ADD,0,&epoll_stdin);epoll_ctl(epfd,EPOLL_CTL_ADD,server,&epoll_server);int eplen = 2;while(1){// 提前准备一个激活列表struct epoll_event list[20] = {0};int count = epoll_wait(epfd,list,20,-1);for(int i=0;i<count;i++){int fd = list[i].data.fd;if(fd == 0){char buf[1024] = "";scanf("%s",buf);getchar();printf("键盘输入数据:%s\n",buf);continue;}if(fd == server){printf("有客户端连接\n");struct sockaddr_in client_addr = {0};int client_len = sizeof(client_addr);int client = accept(server,(struct sockaddr*)&client_addr,&client_len);printf("新连接的客户端的ip = %s\n",inet_ntoa(client_addr.sin_addr));printf("新连接的客户端的port = %d\n",ntohs(client_addr.sin_port));struct epoll_event epoll_client = {.events = EPOLLIN , .data.fd = client};epoll_ctl(epfd,EPOLL_CTL_ADD,client,&epoll_client);eplen ++;continue;}pack_t pack = {0};int res = read(fd,&pack,sizeof(pack));if(res == 0){printf("客户端断开连接\n");epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);continue;}switch(pack.type){case TYPE_REGIST:{regist(&pack,fd,db);break;}case TYPE_LOGIN:{login(&pack,fd,db);break;}}}}return 0;
}
选择使用的是sqlite3数据库

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

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

相关文章

理解 PS1/PROMPT 及 macOS iTerm2 + zsh 终端配置优化指南

终端提示符&#xff08;Prompt&#xff09;是我们在命令行中与 shell 交互的关键界面&#xff0c;它不仅影响工作效率&#xff0c;也影响终端显示的稳定和美观。本文将结合 macOS 上最流行的 iTerm2 终端和 zsh shell&#xff0c;讲解 PS1/PROMPT 的核心概念、常见配置技巧&…

Laravel 原子锁概念讲解

引言 什么是竞争条件 (Race Condition)&#xff1f; 在并发编程中&#xff0c;当多个进程或线程同时访问和修改同一个共享资源时&#xff0c;最终结果会因其执行时序的微小差异而变得不可预测&#xff0c;甚至产生错误。这种情况被称为“竞争条件”。 例子1&#xff1a;定时…

83、形式化方法

形式化方法&#xff08;Formal Methods&#xff09; 是基于严格数学基础&#xff0c;通过数学逻辑证明对计算机软硬件系统进行建模、规约、分析、推理和验证的技术&#xff0c;旨在保证系统的正确性、安全性和可靠性。以下从核心思想、关键技术、应用场景、优势与挑战四个维度展…

解决 Ant Design v5.26.5 与 React 19.0.0 的兼容性问题

#目前 Ant Design v5.x 官方尚未正式支持 React 19&#xff08;截至我的知识截止日期2023年10月&#xff09;&#xff0c;但你仍可以通过以下方法解决兼容性问题&#xff1a; 1. 临时解决方案&#xff08;推荐&#xff09; 方法1&#xff1a;使用 --legacy-peer-deps 安装 n…

算法与数据结构(课堂2)

排序与选择 算法排序分类 基于比较的排序算法&#xff1a; 交换排序 冒泡排序快速排序 插入排序 直接插入排序二分插入排序Shell排序 选择排序 简单选择排序堆排序 合并排序 基于数字和地址计算的排序方法 计数排序桶排序基数排序 简单排序算法 冒泡排序 void sort(Item a[],i…

跨端分栏布局:从手机到Pad的优雅切换

在 UniApp X 的世界里&#xff0c;我们常常需要解决一个现实问题&#xff1a; “手机上是全屏列表页&#xff0c;Pad上却要左右分栏”。这时候&#xff0c;很多人会想到 leftWindow 或 rightWindow。但别急——这些方案 仅限 Web 端&#xff0c;如果你的应用需要跨平台&#xf…

华为服务器管理工具(Intelligent Platform Management Interface)

一、核心功能与技术架构 硬件级监控与控制 全维度传感器管理:实时监测 CPU、内存、硬盘、风扇、电源等硬件组件的温度、电压、转速等参数,支持超过 200 种传感器类型。例如,通过 IPMI 命令ipmitool sdr elist可快速获取服务器传感器状态,并通过正则表达式提取关键指标。 远…

Node.js Express keep-alive 超时时间设置

背景介绍随着 Web 应用并发量不断攀升&#xff0c;长连接&#xff08;keep-alive&#xff09;策略已经成为提升性能和资源复用的重要手段。本文将从原理、默认值、优化实践以及潜在风险等方面&#xff0c;全面剖析如何在 Node.js&#xff08;Express&#xff09;中正确设置和应…

学习C++、QT---30(QT库中如何自定义控件(自定义按钮)讲解)

每日一言你比想象中更有韧性&#xff0c;那些看似艰难的日子&#xff0c;终将成为勋章。自定义按钮我们要知道自定义控件就需要我们创建一个新的类加上继承父类&#xff0c;但是我们还要注意一个点&#xff0c;就是如果我们是自己重头开始造控件的话&#xff0c;那么我们就直接…

【补充】Linux内核链表机制

专题文章&#xff1a;Linux内核链表与Pinctrl数据结构解析 目标&#xff1a; 深入解析Pinctrl子系统中&#xff0c;struct pinctrl如何通过内核链表&#xff0c;来组织和管理其多个struct pinctrl_state。 1. 问题背景&#xff1a;一个设备&#xff0c;多种引脚状态 一个复杂的…

本地部署Dify、Docker重装

需要先安装一个Docker&#xff0c;Docker就像是一个容器&#xff0c;将部署Dify的空间与本地环境隔离&#xff0c;避免因为本地环境的一些问题导致BUG。也确保了环境的统一&#xff0c;不会出现在自己的电脑上能跑但是移植到别人电脑上就跑不通的情况。那么现在就开始先安装Doc…

【每天一个知识点】非参聚类(Nonparametric Clustering)

ChatGPT 说&#xff1a;“非参聚类”&#xff08;Nonparametric Clustering&#xff09;是一类不预先设定聚类数目或数据分布形式的聚类方法。与传统“参数聚类”&#xff08;如高斯混合模型&#xff09;不同&#xff0c;非参聚类在建模过程中不假设数据来自于已知分布数量的某…

人形机器人CMU-ASAP算法理解

一原文在第一阶段&#xff0c;用重定位的人体运动数据在模拟中预训练运动跟踪策略。在第二阶段&#xff0c;在现实世界中部署策略并收集现实世界数据来训练一个增量&#xff08;残差&#xff09;动作模型来补偿动态不匹配。&#xff0c;ASAP 使用集成到模拟器中的增量动作模型对…

next.js刷新页面时二级菜单展开状态判断

在 Next.js 中保持二级菜单刷新后展开状态的解决方案 在 Next.js 应用中&#xff0c;当页面刷新时保持二级菜单的展开状态&#xff0c;可以通过以下几种方法实现&#xff1a; 方法1&#xff1a;使用 URL 参数保存状态&#xff08;推荐&#xff09; import { useRouter } from n…

网络基础DAY13-NAT技术

NAT技术internet接入方式&#xff1a;ADLS技术&#xff1a;能够将不同设备的不同信号通过分离器进行打包之后再internet中传输&#xff0c;到另一端的分离器之后再进行分离。传输到不同的设备中去。常见光纤接入方式internet接入认证方式&#xff1a;PPPoE&#xff1a;先认证再…

HBuilderX中设置 DevEco Studio路径,但是一直提示未安装

前言&#xff1a; HBuilderX中设置 DevEco Studio路径&#xff0c;但是一直提示未安装。 报错信息&#xff1a; 检测到鸿蒙工具链&#xff0c;请在菜单“工具->设置->运行配置”中设置鸿蒙开发者工具路径为 DevEco Studio 的安装路径&#xff0c;请参考 报错原因…

什么是GNN?——聚合、更新与循环

在传统的深度学习中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;擅长处理网格结构数据&#xff08;如图像&#xff09;&#xff0c;循环神经网络&#xff08;RNN&#xff09;擅长处理序列数据&#xff08;如文本&#xff09;。但当数据以图的形式存在时&#xff08;如…

深入解析 Django REST Framework 的 APIView 核心方法

在 Python 3 中&#xff0c;Django 的 APIView 类是 Django REST Framework&#xff08;DRF&#xff09;中用于构建 API 视图的核心基类。它提供了一个灵活的框架来处理 HTTP 请求&#xff0c;并通过一系列方法支持认证、权限检查和请求限制等功能。self.perform_authenticatio…

神经网络——卷积层

目录 卷积层介绍 Conv2d 卷积动画演示 卷积代码演示 综合代码案例 卷积层介绍 卷积层是卷积神经网络&#xff08;CNN&#xff09;的核心组件&#xff0c;它通过卷积运算提取输入数据的特征。 基本原理 卷积层通过卷积核&#xff08;过滤器&#xff09;在输入数据&…

神经网络——线性层

在机器学习中&#xff0c;线性层&#xff08;Linear Layer&#xff09; 是一种基础的神经网络组件&#xff0c;也称为全连接层&#xff08;Fully Connected Layer&#xff09; 或密集层&#xff08;Dense Layer&#xff09;。 其严格的数学定义为&#xff1a;对输入数据执行线…