使用epoll与sqlite3进行注册登录

news/2025/2/13 23:27:07/

将 epoll 服务器 客户端拿来用

客户端:写一个界面,里面有注册登录

服务器:处理注册和登录逻辑,注册的话将注册的账号密码写入数据库,登录的话查询数据库中是否存在账号,并验证密码是否正确

额外功能:客户端登录的时候,服务器向客户端发送一个验证码,只有验证码也正确的时候,才能登录成功·

server.c

#include <stdio.h>
#include <string.h>
#include <unistd.h> 
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
#include <sys/epoll.h>
#include <sqlite3.h>
#include <time.h>
typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;int sqllen;enum Type{TYPE_REGIST,TYPE_LOGIN
};typedef struct pack{enum Type type;char name[20];char pwd[20];int auth;
}pack_t;void read_data(int client);
int callback(void* arg,int argc,char** argv,char** col);void* thread_main(void* arg)//验证码验证
{int client=*(int *)arg;pack_t pack={0};srand(time(0));pack.auth=rand()%10000+1;int test=pack.auth;write(client,&pack,sizeof(pack));read(client,&pack,sizeof(pack));						if(test==pack.auth){					printf("登录成功");}else{printf("验证码错误\n");}}int main(int argc, const char *argv[])
{if(argc!=2){printf("请输入端口号\n");return 0;}int port=atoi(argv[1]);//为服务器准备套接字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=inet_addr("0.0.0.0");//为套接字绑定ip和portif(bind(server,(addr_t*)&addr,sizeof(addr))==-1){perror("bind");return 1;}//监听listen(server,10);//动态监视列表int epfd=epoll_create1(EPOLL_CLOEXEC);//设定需要监视描述符,及激活形式struct epoll_event event_server={.events=EPOLLIN, .data.fd=server};struct epoll_event event_stdin={.events=EPOLLIN, .data.fd=0};//添加到监视列表epoll_ctl(epfd,EPOLL_CTL_ADD,server,&event_server);epoll_ctl(epfd,EPOLL_CTL_ADD,0,&event_stdin);//准备数组,存放激活的描述符struct epoll_event arr[50]={0};while(1){int len=epoll_wait(epfd,arr,50,-1);for(int i=0;i<len;i++){int fd=arr[i].data.fd;//取出激活的描述符if(fd==server){printf("有新的客户端链接\n");int client=accept(server,0,0);struct epoll_event epoll_client={.events=EPOLLIN,.data.fd=client};epoll_ctl(epfd,EPOLL_CTL_ADD,client,&epoll_client);}else if(fd==0){char buf[64]="";scanf("%63s",buf);while(getchar()!=10);printf("键盘输入值为:%s\n",buf);}else{read_data(fd);}}}return 0;
}void read_data(int client)
{pack_t pack={0};int res=read(client,&pack,sizeof(pack));if(res==0){printf("断开连接\n");}sqlite3* db=NULL;if(sqlite3_open("./login.db",&db)!=SQLITE_OK){printf("数据库打开失败\n");return ;}switch(pack.type){case TYPE_REGIST:{char sql[128]="";char* errmsg=NULL;sprintf(sql,"insert into login(name,pwd) values('%s','%s')",pack.name,pack.pwd);if(sqlite3_exec(db,sql,0,0,&errmsg)!=SQLITE_OK){fprintf(stderr,"errmsg=%s\n",errmsg);}printf("注册成功\n");break;}case TYPE_LOGIN:{int flag=0;pack_t arr[20]={0};char* sql="select*from login;";char* errmsg=NULL;if(sqlite3_exec(db,sql,callback,arr,&errmsg)!=SQLITE_OK){fprintf(stderr,"errmsg=%s\n",errmsg);}for(int i=0;i<sqllen;i++){if(strcmp(arr[i].name,pack.name)==0 && strcmp(arr[i].pwd,pack.pwd)==0)//判断登录{pthread_t id;pthread_create(&id,0,thread_main,&client);//线程判断验证码pthread_detach(id);flag=1;}}if(flag==0){printf("登录失败\n");}}}return ;
}int callback(void* arg,int argc,char** argv,char** col)
{pack_t* arr=(pack_t*)arg;strcpy(arr[sqllen].name,argv[0]);strcpy(arr[sqllen].pwd,argv[1]);sqllen++;printf("一共%d个数据\n",sqllen);return 0;	
}

client.c

#include <stdio.h>
#include <string.h>
#include <unistd.h> 
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;enum Type{TYPE_REGIST,TYPE_LOGIN
};typedef struct pack{enum Type type;char name[20];char pwd[20];int auth;
}pack_t;void* thread_main(void* arg)
{int client=*(int *)arg;pack_t pack;read(client,&pack,sizeof(pack));printf("验证码为:%d\n",pack.auth);printf("请输入验证码\n");scanf("%d",&pack.auth);while(getchar()!=10);write(client,&pack,sizeof(pack));}int main(int argc, const char *argv[])
{if(argc!=2){printf("请输入端口号\n");return 0;}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.86");if(connect(client,(addr_t*)&addr,sizeof(addr))==-1){perror("connect");return 1;}while(1){int ch=-1;printf("请选择\n");printf("1:注册\n");printf("2:登录\n");printf("0:退出\n");scanf("%d",&ch);while(getchar()!=10);switch(ch){case 1:{pack_t pack = {0};printf("请输入账号:");scanf("%s",pack.name);while(getchar()!=10);printf("请输入密码:");scanf("%s",pack.pwd);while(getchar()!=10);pack.type = TYPE_REGIST;write(client,&pack,sizeof(pack));break;}case 2:{pack_t pack = {0};printf("请输入账号:");scanf("%s",pack.name);while(getchar()!=10);printf("请输入密码:");scanf("%s",pack.pwd);while(getchar()!=10);pack.type = TYPE_LOGIN;write(client,&pack,sizeof(pack));pthread_t id;pthread_create(&id,0,thread_main,&client);pthread_detach(id);break;}case 0:{exit(0);	}}}return 0;
}

 


http://www.ppmy.cn/news/1571818.html

相关文章

现代神经网络QA(LeNet/AlexNet/VGG/NiN/GooleNet/ResNet)-----一篇搞懂

现代神经网络Q&A-----一篇搞懂 LeNet核心架构 经典卷积神经网络的包括&#xff1a; 带填充以保持分辨率的卷积层&#xff1b;非线性激活函数&#xff0c;如ReLU&#xff1b;汇聚层&#xff0c;如最大汇聚层。 pooling时&#xff0c;使用avg还是max&#xff1f; max&…

JavaScript系列(71)--函数式编程进阶详解

JavaScript函数式编程进阶详解 &#x1f3af; 今天&#xff0c;让我们深入探讨JavaScript函数式编程的进阶内容。函数式编程是一种强大的编程范式&#xff0c;它通过使用纯函数和不可变数据来构建可预测和可维护的应用程序。 函数式编程进阶概念 &#x1f31f; &#x1f4a1;…

开源、免费项目管理工具比较:2025最新整理30款

好用的开源、免费版项目管理系统有&#xff1a;1.Redmine&#xff1b;2. Taiga&#xff1b;3. OpenProject&#xff1b; 4.ProjectLibre&#xff1b; 5.GanttProject&#xff1b; 6.Tuleap&#xff1b; 7.Trac&#xff1b;8. Phabricator&#xff1b; 9.Notion&#xff1b; 10.…

SQL最佳实践(笔记)

写在前面&#xff1a; 之前baeldung的Java Weekly &#xfeff;Reviews里面推荐了一篇关于SQL优化的文章&#xff0c;正好最近在学习数据库相关知识&#xff0c;记一些学习笔记 原文地址&#xff1a;SQL Best Practices Every Java Engineer Must Know 1. 使用索引 使用索引…

vite创建的react18的@路径提示配置

1.配置vite.config.ts import { defineConfig } from "vite"; import react from "vitejs/plugin-react"; import path from "path"; export default defineConfig({plugins: [react()],resolve: {alias: {"": path.resolve(__dirnam…

【k8s应用管理】kubernetes Pod控制器

文章目录 Kubernetes Pod 控制器概述DeploymentStatefulSetStatefulSet 核心特性StatefulSet 组成创建 StatefulSet 的步骤配置 NFS 存储&#xff08;示例&#xff09;定义 PV 资源创建 StatefulSet应用配置 验证与操作查看资源状态测试 DNS 解析滚动更新扩展与缩容 与 Deploym…

Conda 包管理:高效安装、更新和删除软件包

Conda 包管理&#xff1a;高效安装、更新和删除软件包 1. 引言 在使用 Anaconda 进行 Python 开发时&#xff0c;包管理是日常操作的核心内容。Conda 提供了一整套高效的工具来管理 Python 环境中的软件包&#xff0c;避免了版本冲突&#xff0c;并确保了环境的一致性。 本篇…

C# 上位机--常量

引言 在 C# 上位机开发过程中&#xff0c;常量是一个基础且重要的概念。合理使用常量可以提高代码的可读性、可维护性和安全性。本文将深入探讨 C# 上位机中常量的定义、使用场景以及相关的示例程序&#xff0c;并通过图文结合的方式让读者更直观地理解常量的作用。 一、什么…