從零實現基于Linux socket聊天室-增加數據庫Sqlite功能-5
之前更新過從0實現聊天室的4篇文章,很多粉絲朋友還是覺得內容相對簡單,本文一口君會在原有代碼基礎上增加數據庫操作功能,后續文章還會增加文件傳輸功能。
本文需要增加數據庫功能,關于數據庫的基礎知識點,表的創建、增刪改查等操作,以及對應的庫函數的使用請參考以下3篇文章:
- 《嵌入式數據庫sqlite3【基礎篇】-基本命令操作,小白一看就懂》
- 《嵌入式數據庫sqlite3【進階篇】-子句和函數的使用,小白一文入門》
- 《如何用C語言操作sqlite3,一文搞懂》
全部掌握后,開始進入本篇。
一. 調整目錄結構
為了方便編譯,現在我們將前面文章的代碼結構做如下調整。
- root@ubuntu:/mnt/hgfs/code/chat# tree .
- .
- ├── chat_client
- │ ├── include
- │ ├── Makefile
- │ ├── obj
- │ │ └── Makefile
- │ └── src
- │ ├── client.c
- │ └── Makefile
- ├── chat.h
- ├── chat_server
- │ ├── bin
- │ │ └── server
- │ ├── data
- │ ├── include
- │ ├── Makefile
- │ ├── obj
- │ │ └── server.o
- │ └── src
- │ ├── Makefile
- │ └── server.c
- └── gcc.sh
- 10 directories, 15 files
最終增加了數據的文件目錄如下:
- peng@ubuntu:/mnt/hgfs/code/chat-sqlite$ tree .
- .
- ├── chat_client
- │ ├── include
- │ ├── Makefile
- │ ├── obj
- │ │ └── Makefile
- │ └── src
- │ ├── client.c
- │ └── Makefile
- ├── chat.h
- ├── chat_server
- │ ├── data
- │ ├── include
- │ │ └── data.h
- │ ├── Makefile
- │ ├── obj
- │ │ └── Makefile
- │ └── src
- │ ├── data.c
- │ ├── Makefile
- │ └── server.c
- ├── clean.sh
- ├── gcc.sh
- ├── user.db
- └── 解壓密碼.txt
- 9 directories, 17 files
clean.sh 用于清除臨時文件gcc.sh 用于編譯整個工程
服務端代碼放置到chat_server目錄下;客戶端代碼放置到chat_client目錄下;
數據庫相關代碼放在chat_server/data下。
chat.h是所有客戶端和服務器都會用到的頭文件,所以放置在根目錄下。
后續增加功能后,新增的頭文件和C文件分別添加到對應工程目錄的include和src目錄下即可。
二、 設計數據庫表
我們之前維護的所有客戶端的信息是用一個全局數組,并且沒有保存功能,現在我們要把所有客戶端的信息全部保存到數據庫中。
數據庫存儲的目錄
- chat_server/data
數據庫名:
- user.db
存儲用戶信息的表名:
- user
表user格式如下:
三、 主要功能操作的語句及函數
數據庫操作最重要的就是語句,下面講解針對不同的功能對應的實現語句
1.創建表user
- CREATE TABLE IF NOT EXISTS user(name TEXT PRIMARY KEY NOT NULL,passwd TEXT NOT NULL,fd INT NOT NULL,regist INT NOT NULL);
2.增加一個用戶
客戶端發送注冊請求后,服務器端注冊用戶信息到數據庫中
數據庫操作語句如下:
- insert into user values('一口Linux', '123456',-1, 1)
功能函數如下:
- int db_add_user(char name[],char passwd[])
- 功能:
- 增加一個用戶,執行該函數前需要先判斷該用戶名是否存在
- 參數:
- name:用戶名
- passwd:密碼
- 返回值:
- -1:失敗
- 1:成功
3.判斷用戶是否在線
客戶端發送登陸命令后,服務器通過該函數判斷該用戶是否已經登陸成功
數據庫操作語句如下:
- select fd from user where name='一口Linux'
功能函數如下:
- int db_user_if_online(char *name,char *passwd)
- 功能:
- 判斷用戶是否在線,該函數主要根據fd的值來判斷用戶是否在線
- 參數:
- name:用戶名
- passwd:密碼
- 返回值:
- 1:在線
- -1:不在線
- -2:用戶不存在
4.判斷某個用戶名是否注冊
用戶發送注冊命令,服務器需要判斷該用戶名是否已經被注冊過
數據庫操作語句如下:
- select regist from user where name='一口Linux'
功能函數如下:
- int db_user_if_reg(char *name)
- 功能:
- 判斷某個用戶名是否注冊過
- 參數:
- name:用戶名
- 返回值:
- 1:注冊過
- -1:沒有注冊過
5.判斷用戶名密碼是否正確
用戶發送登陸命令,需要判斷用戶名密碼是否正確
數據庫操作語句如下:
- select * from user where name='一口Linux' and passwd='123456'
功能函數如下:
- int db_user_pwd_corrct(char *name,char* passwd)
- 功能:
- 判斷客戶端發送的用戶名密碼是否正確
- 參數:
- name:用戶名
- passwd:密碼
- 返回值:
- 1:正確
- -1:用戶名或者密碼不正確
6.用戶上線、下線
用戶登陸成功后,或者發送下線申請,或者異常掉線,需要更新數據庫的狀態。
數據庫操作語句如下:
- UPDATE user set fd=-1 where name='一口Linux'
fd的值是套接字描述符,下線設置為-1,上線設置為對應的>0的值
功能函數如下:
- int db_user_on_off(int fd,char *name,unsigned int on_off)
- 功能:
- 更新數據庫中用戶的fd字段
- 參數:
- fd:套接字描述符
- name:用戶名
- on_off:上線還是下線
- 返回值:
- 1:正確
- -1:失敗
7. 顯示在線用戶
用戶發送顯示在線用戶命令后,服務器從數據庫當中查找所有在線用戶,并將姓名循環發送給客戶端
- int db_list_online_user(int fd)
四、運行結果編譯
- ./gcc.sh
1.服務器啟動
- ./server 9999
端口號設定為9999
2. 客戶端注冊
客戶端啟動
- ./client 127.0.0.1 9999
選擇1 注冊,輸入用戶名密碼即可。
3. 用戶登錄
輸入選項2,輸入剛才注冊的用戶名密碼,如果不一致會提示錯誤
登錄成功:
4. 注冊登錄其他幾個用戶
注冊并登錄新的用戶111、222、333
5. 公聊
選擇選項3,即進入公聊, 用戶yikou向所有用戶說:hello!
可見所有用戶均收到信息。
6. 私聊
用戶yikou向用戶111發送信息:
由下圖可知,只有用戶111收到該信息,其他用戶均沒有收到信息。
7. 顯示在線用戶
8. 查看最終數據庫信息
五、代碼說明
為方便讀者學習增加數據庫和去掉數據之間的差別,
用git維護版本。
切換到沒有數據庫的版本,執行下面命令即可。
- git reset --hard 597330ae0a183c9db8f68b7c9f60df94f8965778
要切回有數據庫的版本執行下面的命令:
- git reset --hard 10bfbfaf2d09ae895313273c960ecfd84663f9fd
使用數據庫后,數據的存儲管理更加方便,數據類型更易于擴充, 邏輯關系也更加清晰。
本文轉載自微信公眾號「一口Linux」