本節內容:
項目實戰:開發一個WEB聊天室
功能需求:
- 用戶可以與好友一對一聊天
- 可以搜索、添加某人為好友
- 用戶可以搜索和添加群
- 每個群有管理員可以審批用戶的加群請求,群管理員可以用多個,群管理員可以刪除、添加、禁言群友
- 可以與聊天室里的人進行臨時會話(與qq群一樣)
- 可以在群中發圖片
- 可以與好友一對一發文件
知識必備:
- django
- html\css\js
- bootstrap
- jquery, ajax
前景介紹
首先我們知道http是無狀態、請求/響應模式的通信模式,就是用戶每次通過瀏覽器點擊一下頁面,都需要重新與WEB服務器建立一次連接,且發送自己的session id給服務器端以使服務器端驗證此用戶的身份。 客戶端若想從web服務器上獲取數據,必須主動發起一個請求,然后接收服務器端的返回,服務器端不會主動往客戶端推送消息。
基於傳統的WEB服務器只會被動響應客戶端請求的這個認知,如果我們想實現WEB實時聊天的需求,基本上只有以下幾種方式:
輪詢(polling)
輪詢 (Polling) 涉及了從客戶端向服務器端發出請求以獲取一些數據,這顯然就是一個純粹的 Ajax HTTP 請求。為了盡快地獲得服務器端事件,輪詢的間隔(兩次請求相隔的時間)必須盡可能地小。但有這樣的一個缺點存在:如果間隔減小的話,客戶端瀏覽器就會發出更多的請求,這些請求中的許多都不會返回任何有用的數據,而這將會白白地浪費掉帶寬和處理資源。
Comet
使用了輪詢的Ajax 非常受限:其不具伸縮性,不提供低延遲通信(只要事件一到達服務器端,它們就以盡可能快的速度到達瀏覽器端)。 Comet 是一個 Web 應用模型,在該模型中,請求被發送到服務器端並保持一個很長的存活期,直到超時或是有服務器端事件發生。在該請求完成后,另一個長生存期的 Ajax 請求就被送去等待另一個服務器端事件。
Comet 的一大優點是,每個客戶端始終都有一個向服務器端打開的通信鏈路。服務器端可以通過在事件到來時立即提交(完成)響應來把事件推給客戶端,或者它甚至可以累積再連續發送。因為請求長時間保持打開的狀態,故服務器端需要特別的功能來處理所有的這些長生存期請求。
Comet的實現主要有兩種方式:
基於Ajax的長輪詢(long-polling)方式
瀏覽器發出XMLHttpRequest 請求,服務器端接收到請求后,會阻塞請求直到有數據或者超時才返回,瀏覽器JS在處理請求返回信息(超時或有效數據)后再次發出請求,重新建立連接。在此期間服務器端可能已經有新的數據到達,服務器會選擇把數據保存,直到重新建立連接,瀏覽器會把所有數據一次性取回。
Forever Iframe(永存的 Iframe)
此技術涉及了一個置於頁面中的隱藏 Iframe 標簽,該標簽的 src
屬性指向返回服務器端事件的 servlet 路徑。每次在事件到達時,servlet 寫入並刷新一個新的 script 標簽,該標簽內部帶有 JavaScript 代碼,iframe 的內容被附加上這一 script 標簽,標簽中的內容就會得到執行。
WebSocket
如果說Ajax的出現是互聯網發展的必然,那么Comet技術的出現則更多透露出一種無奈,僅僅作為一種hack技術,因為沒有更好的解決方案。Comet解決的問題應該由誰來解決才是合理的呢?瀏覽器,html標准,還是http標准?主角應該是誰呢?本質上講,這涉及到數據傳輸方式,http協議應首當其沖,是時候改變一下這個懶惰的協議的請求/響應模式了。
W3C給出了答案,在新一代html標准html5中提供了一種瀏覽器和服務器間進行全雙工通訊的網絡技術Websocket。從Websocket草案得知,Websocket是一個全新的、獨立的協議,基於TCP協議,與http協議兼容、卻不會融入http協議,僅僅作為html5的一部分。於是乎腳本又被賦予了另一種能力:發起websocket請求。這種方式我們應該很熟悉,因為Ajax就是這么做的,所不同的是,Ajax發起的是http請求而已。
與http協議不同的請求/響應模式不同,Websocket在建立連接之前有一個Handshake(Opening Handshake)過程,在關閉連接前也有一個Handshake(Closing Handshake)過程,建立連接之后,雙方即可雙向通信。
以上幾種實現方式的優缺點
輪詢:客戶端定時向服務器發送Ajax請求,服務器接到請求后馬上返回響應信息並關閉連接。
優點:后端程序編寫比較容易。
缺點:請求中有大半是無用,浪費帶寬和服務器資源。
實例:適於小型應用。
長輪詢:客戶端向服務器發送Ajax請求,服務器接到請求后hold住連接,直到有新消息才返回響應信息並關閉連接,客戶端處理完響應信息后再向服務器發送新的請求。
優點:在無消息的情況下不會頻繁的請求,耗費資源小。
缺點:服務器hold連接會消耗資源,返回數據順序無保證,難於管理維護。
實例:WebQQ、Hi網頁版、Facebook IM。
長連接:在頁面里嵌入一個隱蔵iframe,將這個隱蔵iframe的src屬性設為對一個長連接的請求或是采用xhr請求,服務器端就能源源不斷地往客戶端輸入數據。
優點:消息即時到達,不發無用請求;管理起來也相對方便。
缺點:服務器維護一個長連接會增加開銷。
實例:Gmail聊天
Flash Socket:在頁面中內嵌入一個使用了Socket類的 Flash 程序JavaScript通過調用此Flash程序提供的Socket接口與服務器端的Socket接口進行通信,JavaScript在收到服務器端傳送的信息后控制頁面的顯示。
優點:實現真正的即時通信,而不是偽即時。
缺點:客戶端必須安裝Flash插件;非HTTP協議,無法自動穿越防火牆。
實例:網絡互動游戲。