天天看點

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’);來進行清除緩沖區。

繼續閱讀