網編數據庫小練習

搭建服務器客戶端,要求 服務器使用 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
英文地址,請注明出處:http://en.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;對輸入數據執行線…