竇立君閆志剛韓坷罕
摘 要:聊天軟件已廣泛應(yīng)用于人們的生活中,給人們的信息收集與交流帶來了便利。詳細介紹了如何基于Qt開發(fā)具有用戶注冊、用戶資料維護、用戶列表下發(fā)、登錄校驗、消息轉(zhuǎn)發(fā)、文件傳輸?shù)裙δ艿木W(wǎng)絡(luò)聊天軟件服務(wù)器端。
關(guān)鍵詞關(guān)鍵詞:Qt;網(wǎng)絡(luò)聊天;消息轉(zhuǎn)發(fā);服務(wù)器端;文件傳輸
DOIDOI:10.11907/rjdk.162422
中圖分類號:TP319
文獻標識碼:A 文章編號文章編號:16727800(2016)011010602
0 引言
隨著聊天軟件應(yīng)用于人們生活的各個方面,為人們的工作、生活提供了很多便利,人們可以通過互聯(lián)網(wǎng)進行信息的收集和整理,以及與不同地方的人交流。第一個具有影響力的即時通訊軟件是ICQ,它在1996年底推出,現(xiàn)在已擁有245個國家的大約2億用戶。目前的聊天軟件基本都是由服務(wù)器端和客戶端兩部分組成,其中客戶端分為Web版和本地版。無論哪種版本,它們都需要通過與服務(wù)器端的通信來實現(xiàn)最終功能。本文從服務(wù)器端功能分析、工作流程、關(guān)鍵代碼設(shè)計等方面闡述了聊天軟件服務(wù)器端的設(shè)計過程[1]。
1 系統(tǒng)分析
對服務(wù)器的功能需求進行分析,是成功構(gòu)建一個聊天系統(tǒng)服務(wù)器的第一步,該步驟對于之后設(shè)計服務(wù)器的模塊工作是不可或缺的。即時聊天系統(tǒng)服務(wù)器的需求分析具體分為以下幾部分:
(1)登錄校驗。
輸入:來自客戶端的用戶名和密碼。
處理流程:與數(shù)據(jù)庫中的用戶名和密碼匹配,并反饋結(jié)果給客戶端。
輸出:匹配成功或失敗。
(2)用戶注冊。
輸入:來自客戶端的用戶名和密碼。
處理流程:在數(shù)據(jù)庫中寫入新用戶名和密碼,并反饋結(jié)果給客戶端。
輸出:新建成功或失敗。
(3)消息轉(zhuǎn)發(fā)。
輸入:客戶端發(fā)送的聊天信息。
處理流程:根據(jù)需要發(fā)送的用戶名進行轉(zhuǎn)發(fā),用戶不在線時另作處理。
輸出:轉(zhuǎn)發(fā)信息給發(fā)往方。
(4)文件傳輸。
輸入:客戶端發(fā)送的文件數(shù)據(jù)。
處理流程:直接轉(zhuǎn)發(fā)到發(fā)往方。
輸出:轉(zhuǎn)發(fā)數(shù)據(jù)給發(fā)往方。
(5)用戶資料維護。
輸入:客戶端發(fā)送的更新請求。
處理流程:按請求更新數(shù)據(jù)庫中對應(yīng)的數(shù)據(jù)。
輸出:更新成功或失敗。
(6)用戶列表下發(fā)。
輸入:用戶登錄成功。
處理流程:當某用戶登錄成功后,下發(fā)在線用戶列表給該用戶。
輸出:在線用戶列表。
根據(jù)服務(wù)器端的需求分析,進行功能模塊的劃分,包括封包解析模塊、封包生成模塊、封包分發(fā)模塊、數(shù)據(jù)存儲模塊、用戶注冊模塊、用戶登錄模塊、文本信息轉(zhuǎn)發(fā)模塊、離線文本信息轉(zhuǎn)發(fā)模塊、文件傳輸模塊、用戶列表下發(fā)模塊、用戶資料模塊、超時檢測模塊。這些模塊既能獨立完成相關(guān)功能,又能相互協(xié)調(diào),合作完成最終任務(wù)。
2 工作流程
有了完整的模塊劃分,現(xiàn)在需要構(gòu)建服務(wù)器的工作流程,讓服務(wù)器運轉(zhuǎn)起來。此聊天服務(wù)器的核心工作流程,簡單而言,即不斷把消息包分類攤派到各個不同處理模塊中的過程。
服務(wù)器在指定端口上偵聽數(shù)據(jù)包,當接收到數(shù)據(jù)包后,首先調(diào)用封包解析模塊對數(shù)據(jù)包進行解析,獲取命令類型,再根據(jù)不同命令類型調(diào)用不同模塊。模塊處理完成后,再調(diào)用封包生成模塊來打包結(jié)果,把處理結(jié)果發(fā)送給客戶端。
當接收到登錄命令時,將調(diào)用登錄管理模塊判斷是否可以登入系統(tǒng),不管是否能登入,都把結(jié)果打包返回客戶端。如能成功登入,則繼續(xù)調(diào)用用戶列表下發(fā)模塊,把在線用戶列表打包發(fā)送給客戶端;當接收到注冊命令時,將調(diào)用用戶注冊模塊往系統(tǒng)中添加新用戶,注冊模塊會調(diào)用數(shù)據(jù)存儲模塊進行處理,然后把結(jié)果打包返回客戶端;當接收到資料更新命令時,將調(diào)用資料管理模塊,資料管理模塊又會調(diào)用數(shù)據(jù)存儲模塊進行處理,處理完成后把結(jié)果反饋給客戶端;當接收到文本消息時,將調(diào)用文本消息轉(zhuǎn)發(fā)模塊進行處理,該模塊從解析得到的結(jié)果中獲取所要發(fā)送的客戶端并轉(zhuǎn)發(fā)。如果檢測到所要發(fā)送的客戶端不在線,則轉(zhuǎn)入離線消息模塊處理。
用戶登錄后,客戶端會定時發(fā)送心跳包到服務(wù)器,服務(wù)器自動維護此在線狀態(tài)列表,并定時執(zhí)行超時檢測模塊,把超時用戶從在線列表中刪除。
3 關(guān)鍵代碼設(shè)計
Qt使用源代碼級“一次編寫,隨處編譯”的方式構(gòu)建多平臺圖形用戶界面程序,它完全面向?qū)ο笄液苋菀讛U展,為應(yīng)用程序開發(fā)者建立藝術(shù)級圖形用戶界面提供了所需功能,提供了信號與槽的機制替代回調(diào)函數(shù),使組件間的信號傳遞更加安全、簡單。因此,它已經(jīng)成為全世界范圍內(nèi)數(shù)千種成功的應(yīng)用程序的基礎(chǔ),為世界上數(shù)千個最大的公司,包括IBM、摩托羅拉和夏普等提供開發(fā)軟件[2]。
聊天服務(wù)器的工作流程比較簡單,即:收到消息→處理消息→轉(zhuǎn)發(fā)處理后的消息。聊天服務(wù)器啟動時在特定端口監(jiān)聽,當有數(shù)據(jù)到達時,自動判斷消息類型,并進行不同處理,然后根據(jù)處理結(jié)果,將其發(fā)送給客戶端。在具體實現(xiàn)中,消息的接收、發(fā)送與判斷消息類型都比較簡單,工作量較大的是消息處理部分。因為有很多不同命令,對應(yīng)的也有不同處理過程,所以在設(shè)計中需要把這些處理過程分離成單獨的處理邏輯,在類中表現(xiàn)為不同函數(shù)。本模塊設(shè)計并不包含圖形用戶界面的相關(guān)部分,當最終的服務(wù)器軟件需要搭配圖形界面時,只需在聊天服務(wù)器模塊中定義相關(guān)信號,并在合適的時候發(fā)出信號,圖形界面程序即可通過聊天服務(wù)器模塊的信號與槽進行連接,從而實現(xiàn)顯示更新等功能。
3.1 聊天服務(wù)器端類定義
為了利用Qt的信號和槽功能,聊天服務(wù)器類直接從QObject繼承,具體代碼如下 :
class ChatServer : public QObject
{ Q_OBJECT
public:
explicit ChatServer(QObject *parent = 0);
void start(quint16 port=4500); //啟動服務(wù)
private:
void registerUser(const QString& id, const QString& password, const QHostAddress& addr, quint16 port);//注冊用戶
bool login(const QString& id, const QString& password, const QHostAddress& addr, quint16 port);//用戶登錄
void relayMessage(const QString& to, const QString& message, const QFont& font, const QColor& color, const QHostAddress& addr, quint16 port);//轉(zhuǎn)發(fā)聊天消息
void sendFriendsList(const QHostAddress& addr, quint16 port); //發(fā)送用戶列表
void feedback(const QHostAddress& addr, quint16 port); //反饋
void logout(const QHostAddress& addr, quint16 port); //注銷
void keepAlive(const QHostAddress& addr, quint16 port); //激活
QUdpSocket *m_udpSender; //發(fā)送數(shù)據(jù)的UDP對象
QUdpSocket *m_udpReceiver; //監(jiān)聽數(shù)據(jù)的UDP對象
QHash
QHash
QHash
Storage m_storage; //數(shù)據(jù)存儲對象
enum {onlineTimeout = 30}; //在線超時時間
private slots:
void processPendingDatagrams(); //網(wǎng)絡(luò)數(shù)據(jù)處理
void checkTimeout(); //檢查超時狀態(tài)
};
在ChatServer類的實現(xiàn)中,需要注意名稱表、主機表以及激活狀態(tài)表的維護,它們是維持服務(wù)器工作狀態(tài)的核心。為了實現(xiàn)快速查詢,這幾張表都采用Qt中的哈希表QHash進行存儲。例如:名稱表是用戶名到(主機,端口號)的映射,即通過用戶名可以查詢到對應(yīng)的主機地址和端口號,在轉(zhuǎn)發(fā)消息時則要使用到名稱表。
3.2 超時檢測
超時檢測功能由定時器自動執(zhí)行,以實現(xiàn)每隔固定時間更新一次在線狀態(tài)的功能。當?shù)竭_時間點時,程序開始遍歷激活狀態(tài)表中的所有用戶,檢查其最后一次的心跳包時間與當前系統(tǒng)時間的差值是否超過指定的預(yù)期,如果沒有,則表示用戶仍然正常在線;如果超時,則作自動注銷處理。具體代碼如下:
void ChatServer::checkTimeout()
{ QList
QDateTime now = QDateTime::currentDateTime(); //獲取當前系統(tǒng)時間
for (int i = 0; i < keys.length(); ++i) //遍歷所有用戶
{ if (m_aliveTimeHash.value(keys.at(i)).secsTo(now) > onlineTimeout) //檢查用戶是否超時
{ qDebug() << trUtf8("%1 timeout").arg(keys.at(i));
QStringList list = keys.at(i).split(" ");
QHostAddress addr;
addr.setAddress(list.at(0).toInt());
quint16 port = list.at(1).toInt();
logout(addr, port); //用戶超時時作注銷處理
4 結(jié)語
關(guān)鍵代碼介紹之后,其它功能代碼的接口規(guī)范及實現(xiàn)則相對容易,這里不再贅述。服務(wù)器端軟件設(shè)計完成后,配合客戶端軟件完成了消息的傳遞及轉(zhuǎn)發(fā)、客戶端文件傳輸及服務(wù)器端日志記錄等功能。后期將繼續(xù)在數(shù)據(jù)傳輸安全性與可靠性方面進行優(yōu)化,支持客戶端的其它擴展功能,提升用戶體驗。
參考文獻:
[1] 趙茁琳,陳恒如,韓利凱.基于QT的網(wǎng)絡(luò)聊天系統(tǒng)設(shè)計[J].軟件導(dǎo)刊,2015,14(4):114115.
[2] 張春艷.基于Qt的嵌入式圖形用戶界面研究與實現(xiàn)[D].大連:大連海事大學(xué),2008.
[3] 丁林松,華麗琴.Qt4圖形設(shè)計與嵌入式開發(fā)[M].北京:人民郵電出版社,2009.
[4] [英]薩默菲爾德.Qt高級編程[M].北京:電子工業(yè)出版社,2011.
[5] 吳迪.零基礎(chǔ)學(xué)Qt4編程[M].北京:北京航空航天大學(xué)出版社,2010.
[6] 代勇.Visual C++網(wǎng)絡(luò)通信編程技術(shù)詳解[M].北京:機械工業(yè)出版社,2011.
(責(zé)任編輯:黃 ?。?