C語言聊天室項目說明書

網絡聊天室項目說明

  • 項目的目的和意義

該聊天室項目爲利用linux下C語言網絡編程相關知識,採用Server/Client,即服務器與客戶端的基本框架實現。整個項目涉及了socket套接字,線程,嵌入式數據庫sqlite3,select模型等多個知識模塊,服務器整體採用select模型,並不斷監聽客戶端,客戶端中起一個線程,用來實時接受服務器發送的信息。

該聊天室項目可模擬當今的聊天工具中的各個功能,實現最基本的互相發送信息,羣發消息,登陸註冊等功能。完成該項目可很大的提高我們初學者的編程能力,以及面對出現的各種bug的應對解決能力,是一個提升自我的很好途徑。

 

  • 項目的需求分析

1.聊天室支持連接多個客戶端,採用select模型

2.客戶端與服務器的連接,接受信息

3.賬號網名的註冊,登錄,並存檔

4.顯示所以在線好友

5.服務器與客戶端的通信,實現信息轉發(私聊,羣聊)

6.實現管理員權限,可進行禁言,踢人等功能

7.發送表情,常用語句

8.每個用戶都建立各自的聊天記錄文件,服務器保存所以用戶的聊天記錄

 

 

  • 項目的技術方案設計
  1. 服務器socket和select

首先建立socket,用bind進行綁定後,用listen進行對客戶端的監聽。在一個while(1)循環中,採用select對客戶端進行操作,將所以文件描述符放到readfd中,如果是有新的客戶端要進行連接,即sockfd有動靜,就開始accept操作,將新的fd放到readfd中,並修改maxfd的值;如果是其他已經存在的fd有動作,則進行聊天室相關的功能操作。

 

  1. 客戶端的實現

先建立socket,用connect與服務器進行連接,此後先進入賬號登陸註冊的函數,登陸成功後,及賬號函數執行完畢,此時起一個線程,用來實時接受服務器端發送的信息。之後調用聊天室的各種功能的實現函數。在線程中,不斷接受服務器發送的信息,根據標誌位實現各個功能,如私聊位是1,就進行打印收到的信息內容。

 

  1. 賬號註冊登錄

這是需要打開一個數據庫,用來存放帳號密碼網名的信息。註冊時,要進行判斷該賬號是否已經存在,將其與賬號數據庫中的賬號進行逐一比較,若存在相同的則將一個標誌位置一,顯示該帳號已存在,在輸入網名時進行同樣的查重操作。登陸時,輸入賬號時判斷該帳號是否已經登錄,以及是否存在,輸入密碼後與數據庫相應位置的信息比較,判斷密碼的對錯。當登陸成功後,將登陸的id,網名信息發送給服務器,服務器形成一個鏈表,用來存放在線用戶的信息,包含網名所對應的文件描述符fd,以便後期使用,登錄時輸入賬號查看是否在已經在線就是向服務器發送一個信號,在服務器端遍歷該鏈表,查看是否在線,再發送回客戶端。

 

  1. 私聊羣聊

在客戶端處選擇該功能,輸入發送對象的網名,然後就可以輸入信息併發送。定義一個用來專門發送信息的struct,Sendbuf,設置私聊的標誌位,私聊時將其置一,服務器端判斷該位如果是一就進行私聊操作,將網名和發送的內容分別存放到Sendbuf中,服務器接收到後,根據網名來遍歷在線用戶鏈表,查找到相應的fd,再將信息轉發給該用戶,若是羣聊,就將信息轉發給鏈表中的所以用戶。

 

  1. 管理員功能

在每個客戶端設置一個管理員標誌位,初始化爲0,若選擇註冊會員功能,則將其置一,否在在選擇禁言踢人等功能時顯示無權限。禁言時輸入禁言對象,服務器轉發禁言消息給該用戶,該用戶的不可發言標誌位置一,則不能進行私聊羣聊。踢人時輸入網名,服務器向其發送退出信號,則該客戶端退出聊天室,及進程被終止。

 

  1. 發送表情,常用語

設置特有的標識符代表相應表情和常用語句,之後進行私聊操作,發送相應的表情和常用語。

 

  1. 保存聊天記錄

在客戶端的私聊羣聊發送表情常用語功能處,發送之後將其內容和發送者發送對象的網名存放到相應用戶的數據庫表中,在接受端同樣進行該操作,即可保存用戶的聊天記錄。在服務器端,進行轉發操作時,將發送者發送對象網名和聊天內容存放到系統的聊天記錄文件中,便實現了服務器端的聊天記錄保存。

 

四、遇到的問題與解決途徑及方法

1.重複登錄的問題

問題:由於每個id登陸後,在接受消息發送消息時,都會打開用其id命名的數據庫表,如果同時登錄了一個賬號,在接受發送消息時,兩個進程會同時打開一個數據庫表,這時就會exec函數就會出錯,進程退出。

 

解決方法:這時就需要限制帳號的重複登錄,保證一個賬號只能登錄一次,在登陸的時候,將輸入的id號發送給服務器,遍歷服務器中在線用戶信息的鏈表,若已存在則打印該帳號已登錄。這樣就可以保證每個帳號只能登陸一次。

 

  1. 退出時出現的問題

問題:在一個客戶端退出時,如果沒有相應的操作,在服務器端該客戶端的相關信息還是存在的,在其他用戶聊天查看好友時會出現問題,並且此時若有其他客戶端連接,所產生的fd也會出錯,所以在退出時一定要有相關操作。程序異常退出時,如遇到ctrl+c信號,也應有相應操作。

 

解決方法:遇到ctrl+c信號時,客戶端應獲取該信號,即SIGINT,獲取後執行一個函數,用來關閉相應的fd,並在服務器端刪除該用戶的在線信息。在功能選擇界面也添加一個退出選項,執行相關操作。

 

  1. MaxFd的改變問題

問題:在同時連接了幾個客戶端後,通訊都正常,但是關閉中間的客戶端時,會出現之後開啓的客戶端無法與服務器通信的現象。

 

解決方法:在調試了多次之後,發現問題出在MaxFd的改變上,MaxFd必須要比select中的那個readfd中的最大的成員的fd的數值要大,如果小了,就會出線上述問題,造成之後的fd無法通信。在每次有客戶端退出時,一定要將fd數組中的所以fd遍歷一遍,找到最大的再賦值給MaxFd,一定要確保MaxFd足夠大纔可以。

 

  1. 功能選擇輸入時輸入出錯的問題

問題:由於各個功能的選擇標號是int型,正常應該輸入一個數字,但如果隨便輸入各種字符的話就會出錯,並且由於緩衝區的問題,會繼續影響之後的功能選擇

 

解決方法:分兩步,scanf這個函數也是有返回值的,如果沒有獲取成功會返回0,可以通過這個來判斷是否獲取到了int型數據,如果失敗了,就需要進行清除緩衝區,查找了資料,可以用while((ch = getchar()) != EOF && ch != ‘\n’);來進行清除緩衝區。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章