|
php聊天室技術 黃國輝
1.前言
上網(wǎng)聊天是時下最流行的交友方式。各大網(wǎng)站推出的聊天室都各具特色。
聊天室主要分為WebChat、BBSChat兩種。BBSChat是基于TelNET的Tcp協(xié)議,是BBS的附設功能,需要客戶端TelNET程序。WebChat則采用瀏覽器方式,實際上是一個多人共同使用的CGI程序。其基本原理是把每個用戶的發(fā)言通過瀏覽器傳給系統(tǒng),再由系統(tǒng)收集處理后分發(fā)給特定用戶。
WebChat一般采用Server Push或Client Pull技術。兩種技術的區(qū)別在于使用不同的方式將數(shù)據(jù)分發(fā)給用戶,Server Push是由服務器將數(shù)據(jù)以多重MIME編碼,推給(push)使用者端,目前較少網(wǎng)站使用這種方式。Client Pull則是用戶從服務器拉(pull)所要的數(shù)據(jù)。
最常用的Client Pull就是利用Html語言的Meta標簽http-equiv="Refresh" 的屬性,每隔一段時間就檢查服務器上是否有新的數(shù)據(jù)。例如,每隔5秒鐘就會刷新一次頁面。這種方法簡單有效,缺點是刷新時會產(chǎn)生閃爍的現(xiàn)象;而且為了保持效率,每次刷新都會把舊的聊天內(nèi)容清除,用戶想查看或保留對話內(nèi)容都很不方便。為此,采用JavaApplet作為聊天室的前端,利用刷新把從服務器Pull的數(shù)據(jù)通過JavaApplet來顯示也是一種解決方案。還有就是本文要介紹的使聊天程序保持連線的方案。方法一,把聊天程序設置為無限大,就能使瀏覽器不停地保持下載的連線狀態(tài);方法二,聊天程序中存在著無限循環(huán),因為可以方便地設置更高級的功能,所以在此選擇采用。
Web服務器采用FreeBSD+Apache,原因是兩者的組合具有最強的性能,而且花費為零。還需要考慮的是用什么方式來存放數(shù)據(jù)呢。用文件相對而言容易實現(xiàn),但是多人使用,頻繁地對同一文件進行IO操作,難免會影響效率,況且FreeBSD的IO性能不佳。可以考慮使用RamDisk,將文件整個放進內(nèi)存,以提高速度。或者在內(nèi)存中劃分出一塊高速空間用以數(shù)據(jù)存放。筆者使用的是數(shù)據(jù)庫方式:MySQL。因為該數(shù)據(jù)庫就是為大批量用戶同時使用而設計,利用它可以省去設計高速空間操作的復雜編寫,速度也可得到保證。如將整個數(shù)據(jù)庫放進內(nèi)存,效果更好。
程序用php+Html+JavaScript編寫。聊天室主要是對Html的Form中的各種元素進行操作。JavaScript是基于對象的語言,對Html中的各種元素皆當作對象看待,所以每個元素的方法和屬性都很豐富,操作比較方便。而php只有在Form經(jīng)過Post后,將Form中的元素轉成對應的變量,才能處理用戶輸入的數(shù)據(jù)。從交互性來說比較差,這也是使用JavaScript的原因。采用php的原因是因為比起其它CGI語言,其速度和安全性都較佳,開發(fā)也比較容易。
2. 不斷刷新的聊天室
一個標準的聊天室頁面由三個Frame組成,分別是顯示在線用戶的Online、用戶發(fā)言及功能設置的Say和顯示聊天內(nèi)容的List。用戶在Say Frame中敲入發(fā)言內(nèi)容后按發(fā)送,數(shù)據(jù)經(jīng)過處理后保存在Mysql數(shù)據(jù)庫,同時被保存的還包括發(fā)言人、聊天對象及發(fā)言的時間。用戶一進入聊天室,List Frame從Mysql數(shù)據(jù)庫中把發(fā)言時間大于用戶進入時間的發(fā)言提出顯示出來。而后續(xù)顯示新的發(fā)言內(nèi)容的關鍵,在于顯示聊天內(nèi)容的那段程序是無限循環(huán)的。
List Frame程序概要:
復制代碼 代碼如下:
$db=mysql_pconnect(localhost,root); #Mysql數(shù)據(jù)庫連接
mysql_select_db(chat,$db);
顯示歡迎進入聊天室
設置$init為數(shù)據(jù)庫中發(fā)言時間比
進入時間大的第一個數(shù)據(jù)的ID號 #是數(shù)據(jù)提取的標志位
while (1==1) { #無限循環(huán)開始
提取從$init到最后的數(shù)據(jù);
while (每一個數(shù)據(jù)$text) {
$emote=strip_tags($text); #防止用戶直接輸入Html語言
if (eregi("^/",$emote)) #判斷發(fā)言是否系統(tǒng)命令(以/開頭)
系統(tǒng)特殊處理
else 顯示發(fā)言
}
設置$init為最后數(shù)據(jù)的ID號
flush(); #清出輸出緩沖,使發(fā)言馬上顯示
sleep(2); #使程序暫停2秒,節(jié)省系統(tǒng)資源
mysql_free_result($result); #釋放數(shù)據(jù)庫結果占用的內(nèi)存
}
因為程序無限循環(huán),在每次循環(huán)中輸出的發(fā)言是先置入輸出緩沖區(qū)內(nèi)。通過flush()馬上把緩沖區(qū)的內(nèi)容向用戶的List Frame送出,達到了實時的聊天效果。循環(huán)最后要釋放Mysql結果集占用的內(nèi)存,否則因為無限循環(huán)的緣故,系統(tǒng)資源很快會被耗盡。
用戶在Login后將建立一個Online的表用于在線用戶的統(tǒng)計,主要是為了防止User表過大,程序中頻繁用到的檢索會拖慢系統(tǒng)的運作。這其中用的最多的是Online Frame,在采用Client Pull的Refresh Meta,每隔一段時間就會查詢Online表,以刷新在線的用戶。如果用戶不發(fā)言超過規(guī)定時間,系統(tǒng)會調(diào)用自定義函數(shù)將用戶設為TimeOut,強制將其退出聊天室。
3. 用戶功能簡介
用戶的功能設置在Say Frame中,可以選擇發(fā)言貼圖、說話的語氣等。發(fā)言經(jīng)過特殊的處理后存儲到Mysql,例如選擇了一個貼圖后,系統(tǒng)將添加到發(fā)言的前面,就可以實現(xiàn)貼圖的效果。
對于聊天室常用到的Emote,例如用戶A輸入“/hello”按發(fā)送,List Frame中顯示出來的是“用戶A愉快地和大家打招呼”,為了保持效率,用戶輸入的Emote會原文直接保存到數(shù)據(jù)庫,而解析轉換的工作由List Frame來完成。
悄悄話只有自己和聊天對象可以看到,實現(xiàn)上因為發(fā)言預先保存有發(fā)言人和聊天對象,只要做一個簡單的判斷即可。還有聊天室常有的屏蔽某用戶發(fā)言的功能,通過設置一個臨時的陣列來實現(xiàn),沒必要保存在用戶的數(shù)據(jù)庫中。
聊天室人多的時候,大家爭先發(fā)言常使人眼花繚亂,這時可以選擇是否屏蔽無關的發(fā)言,即意味著只要不是對所有人和自己的發(fā)言將不會顯示出來。當然,因為系統(tǒng)會用特殊的顏色來標識和自己有關的發(fā)言,就算不選擇該功能,用戶還是能快速地從眾多發(fā)言中找到和自己相關的。
用戶可以在特定時間(系統(tǒng)比較空閑時)將當天和自己有關的發(fā)言打包。因為存儲發(fā)言的表數(shù)據(jù)增長速度很快,為保持運行效率,系統(tǒng)隔天就會把它復制后清空。這樣用戶檢索打包發(fā)言內(nèi)容就不會影響聊天系統(tǒng)的運作。
出于安全的考慮,聊天室的管理功能是獨立的,并沒放在聊天頁面中。主要有用戶資料管理和將搗亂用戶Kick Out(踢人)兩種功能。將用戶踢出聊天室后將使他在一定的時間內(nèi)不能再進入聊天室。
聊天室的安全要求雖然不象電子商務那樣高,但如果用戶被冒名頂替、用戶的發(fā)言被竊聽,或者亂踢人,是非常令人不快的。用戶都要在Login中填寫名字和密碼才能進入聊天室,但是通過查看Login的源代碼,雖然不能看到php的部分,Htnl部分的源碼卻顯示Login是調(diào)用Chat.php程序從而進入聊天室的。所以為了防止用戶直接進入聊天室,系統(tǒng)會首先判斷新建立的聊天室是否由Login產(chǎn)生的,不是則退出。同理,在聊天室的List Frame和Post Frame也可加上這樣的防護。當然,在List Frame和Post Frame中檢查用戶的身份和密碼,就萬無一失了,只是加重了系統(tǒng)的負擔。
綜上所述,能看到系統(tǒng)的源代碼無疑是危險的開端,所以系統(tǒng)的編寫盡量用看不到源碼的php;設置由Login開啟的聊天室隱藏了瀏覽器的工具條、狀態(tài)欄等,并且屏蔽了鼠標的右鍵及快捷鍵。
4. 總結
用php編寫的聊天室具有高效穩(wěn)定的特點,是編寫網(wǎng)絡交互程序的最佳選擇。
參考文獻:
[1] Rasmus Lerdorf著. php Manual [M].電子文檔,2000
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。