(中國(guó)電信荊州分公司,湖北 荊州434020)
隨著互聯(lián)網(wǎng)技術(shù)和計(jì)算機(jī)技術(shù)在不斷進(jìn)步,通過(guò)互聯(lián)網(wǎng)進(jìn)行通訊交流的人越來(lái)越多,聊天通訊系統(tǒng)也在不斷地優(yōu)化,開(kāi)發(fā)設(shè)計(jì)技術(shù)也在不斷地提高。下面,筆者基于Java語(yǔ)言對(duì)一個(gè)小型實(shí)用即時(shí)網(wǎng)絡(luò)聊天通訊系統(tǒng)的實(shí)現(xiàn)展開(kāi)分析和設(shè)計(jì)。
整個(gè)系統(tǒng)的總體實(shí)現(xiàn)如圖1所示??蛻?hù)成功登錄后將創(chuàng)建一個(gè)線程來(lái)接收服務(wù)器端的信息并進(jìn)行處理,同樣,服務(wù)器端接收到一個(gè)連接后就為這個(gè)連接創(chuàng)建一個(gè)線程來(lái)對(duì)客戶(hù)的操作進(jìn)行處理。在服務(wù)器端打開(kāi)之后就創(chuàng)建了一個(gè)數(shù)據(jù)源,為客戶(hù)服務(wù)的線程在需要訪問(wèn)數(shù)據(jù)庫(kù)的時(shí)候就從服務(wù)器端的數(shù)據(jù)源里取一個(gè)數(shù)據(jù)庫(kù)的連接來(lái)進(jìn)行數(shù)據(jù)庫(kù)操作,減少了頻繁的數(shù)據(jù)庫(kù)連接和釋放的次數(shù),提高了效率。
圖1 整個(gè)系統(tǒng)的總體實(shí)現(xiàn)
客戶(hù)端與服務(wù)器端之間的消息都是一個(gè)個(gè)實(shí)現(xiàn)了Message接口的對(duì)象,Message接口有一個(gè)方法getType(),該方法返回該對(duì)象的類(lèi)型,在發(fā)送和接收的時(shí)候都是直接對(duì)Message類(lèi)型的對(duì)象進(jìn)行操作[1]。這樣的好處就是在接收發(fā)送信息時(shí)可以統(tǒng)一處理。Message接口的定義如下所示:
具體的消息類(lèi)型都已經(jīng)在PackageType里面進(jìn)行定義,而具體的消息類(lèi)在構(gòu)造時(shí)就要為type斌一個(gè)相應(yīng)的值.目前系統(tǒng)用到的消息類(lèi)和其相應(yīng)的在PackageType里定義的type值如表1所示。
具體的消息類(lèi)因?yàn)橐ㄟ^(guò)網(wǎng)絡(luò)進(jìn)行發(fā)送因此必須實(shí)現(xiàn)Serializable接口,同時(shí)要實(shí)現(xiàn)Message接口。下面就聊天內(nèi)容消息類(lèi)對(duì)具體消息類(lèi)的實(shí)現(xiàn)進(jìn)行分析。
表1 消息包和其對(duì)應(yīng)的type值
在每個(gè)具體消息類(lèi)里面都有一個(gè)成員type,用來(lái)標(biāo)識(shí)消息的類(lèi)型,實(shí)現(xiàn)getType方法返回type,同時(shí)type在構(gòu)造函數(shù)中進(jìn)行賦值。
登錄的信息在登錄窗口進(jìn)行輸入,登錄過(guò)程則調(diào)用客戶(hù)端主窗口的方法來(lái)實(shí)現(xiàn),如果成功登錄登錄窗口就退出,顯示客戶(hù)端主窗口,如果登錄不成功就彈出提示框,用戶(hù)可在登錄窗口修改輸入的信息再進(jìn)行登錄。登錄過(guò)程的順序?yàn)椋孩倏蛻?hù)端連接服務(wù)器端。用公鑰加密生成的密鑰,把加密的密鑰發(fā)送到服務(wù)器端;服務(wù)器端用私鑰解密接收到的密鑰,設(shè)置加密密碼;②客戶(hù)端對(duì)用戶(hù)的密碼進(jìn)行加密,發(fā)送驗(yàn)證信息;服務(wù)器端驗(yàn)證用戶(hù)信息,返回驗(yàn)證結(jié)果,如果失敗就關(guān)閉socket,結(jié)束過(guò)程;③客戶(hù)端驗(yàn)證失敗就提示失敗,結(jié)束過(guò)程;驗(yàn)證成功就顯示主窗口,發(fā)送自己的狀態(tài)信息;服務(wù)器端讀取客戶(hù)的狀態(tài),發(fā)送用戶(hù)的信息;④客戶(hù)端接收自己的信息,存儲(chǔ)下來(lái),服務(wù)器端發(fā)送客戶(hù)的好友列表;⑤客戶(hù)端讀取好友列表。
注冊(cè)的信息在注冊(cè)窗口輸入,注冊(cè)過(guò)程就與服務(wù)器建立一個(gè)連接,把注冊(cè)時(shí)填的信息通過(guò)Regist Message發(fā)送到服務(wù)器,服務(wù)器把注冊(cè)信息添加到數(shù)據(jù)庫(kù),然后通過(guò)RegistResultMessage返回一個(gè)注冊(cè)到的號(hào)碼給客戶(hù)端,如果過(guò)程出現(xiàn)錯(cuò)誤就返回的注冊(cè)到的號(hào)碼為0??蛻?hù)端收到注冊(cè)結(jié)果后把注冊(cè)到的結(jié)果顯示給用戶(hù),或者提示注冊(cè)不成功。由于在數(shù)據(jù)庫(kù)添加記錄后要返回注冊(cè)到的號(hào)碼,所以在數(shù)據(jù)庫(kù)設(shè)計(jì)的時(shí)候hmnum沒(méi)有用到自動(dòng)遞增,而是在注冊(cè)的時(shí)候先得到hmnum的最大值,然后把最大值加1作為注冊(cè)到的帳號(hào),寫(xiě)到數(shù)據(jù)庫(kù),同時(shí)把這個(gè)號(hào)碼返回給客戶(hù)端。
聊天部分是系統(tǒng)的核心,涉及到嚴(yán)格的順序控制和許多的細(xì)節(jié)。首先是在客戶(hù)端的實(shí)現(xiàn),在好友列表的列表項(xiàng)里保存了所有在系統(tǒng)的使用過(guò)程中要用到的信息,有好友的帳號(hào)、好友的昵稱(chēng)、好友的狀態(tài)、好友的頭像、好友的頭像號(hào)和與該好友的聊天窗口。收到該好友的聊天消息時(shí),如果與該好友的聊天窗口還沒(méi)有初始化,就新建一個(gè)與該好友的聊天窗口存儲(chǔ)在好友的列表里,然后把收到消息加入到聊天窗口里;如果與該好友的聊天窗口已經(jīng)建立就直接把收到的消息加入到聊天窗口。如果聊天窗口還沒(méi)有打開(kāi),就把好友的頭像換成跳動(dòng)的頭像來(lái)提示用戶(hù)已收到該好友的聊天信息。如果主窗口已經(jīng)縮進(jìn)到屏幕的上方或者最小化,則系統(tǒng)托盤(pán)會(huì)有消息框提示收到好友的消息。要打開(kāi)與該好在的聊天窗口,只要在主窗口雙擊好友的列表項(xiàng)就行了。如果在好友頭像跳動(dòng)即有收到好友的時(shí)候打開(kāi)窗口就會(huì)顯示已收到的消息,打開(kāi)聊天窗口后就可以與該好友進(jìn)行聊天。
發(fā)送文件的過(guò)來(lái)要由發(fā)送端、服務(wù)器和接收端共同協(xié)作來(lái)完成,要發(fā)送的文件都通過(guò)服務(wù)器來(lái)進(jìn)行中轉(zhuǎn)。文件發(fā)送的順序控制為:①發(fā)送端發(fā)送文件信息,要求發(fā)送文件(發(fā)送文件的線程啟動(dòng));服務(wù)器端向接收端發(fā)送文件信息,要求發(fā)送文件;接收端選擇接收或拒絕,發(fā)送結(jié)束。②服務(wù)器端如果選擇接收,為傳輸文件創(chuàng)建一個(gè)線程,創(chuàng)建serversocket等待發(fā)送端和接收端連接,把serversocket端口發(fā)送給接收端;接收端收到端口,連接到服務(wù)器的serversocket(接收文件的線程啟動(dòng))。③服務(wù)器端與接收端連接上,把serversocket端口發(fā)送給發(fā)送端。④發(fā)送端收到端口,連接到服務(wù)器的serversocket;服務(wù)器端與發(fā)送端連接上后,向發(fā)送端發(fā)送一個(gè)信息,表示已經(jīng)可以開(kāi)始發(fā)送文件的數(shù)據(jù)。⑤發(fā)送端收到信息后發(fā)送數(shù)據(jù),開(kāi)始循環(huán)發(fā)送文件數(shù)據(jù),同時(shí)更新進(jìn)度條和傳輸速度;服務(wù)器端接收發(fā)送端的數(shù)據(jù),再發(fā)送到接收端;接收端接收文件數(shù)據(jù),同時(shí)更新進(jìn)度條和傳輸速度。⑥發(fā)送端傳輸完成,線程結(jié)束;服務(wù)器端傳輸完成,線程結(jié)束;接收端傳輸完成,線程結(jié)束。
[1]Bruce Eckel.Thinking in Java [M].Third Edition.北京:機(jī)械工業(yè)出版社,2004:315-370.