原文:http://www.cnblogs.com/xiezhengcai/p/3957314.html
要理解socket.io ,不得不談談websocket
在html5之前,因為http協議是無狀態的,要實現瀏覽器與服務器的實時通訊,如果不使用 flash、applet 等瀏覽器插件的話,就需要定期輪詢服務器來獲取信息。這造成了一定的延遲和大量的網絡通訊。隨着HTML5 的出現,這一情況有望徹底改觀,它就是 WebSocket 。理論上,Socket能干的事Websocket都能完成,這與需要實現與服務器實時通信的應用來說,如從羊腸小道進入了高速公路。那么,使用Websocket我們要做些什么呢?
首先,我們得先看看websocket的工作機制
工作流程:
瀏覽器通過 JavaScript 向服務器發出建立 WebSocket 連接的請求,連接建立以后,客戶端和服務器端就可以通過 TCP 連接直接交換數據。因為 WebSocket 連接本質上就是一個 TCP 連接,所以在數據傳輸的穩定性和數據傳輸量的大小方面,和傳統輪詢以技術比較,具有很大的性能優勢。
為了建立一個 WebSocket 連接,客戶端瀏覽器首先要向服務器發起一個 HTTP 請求,這個請求和通常的 HTTP 請求不同,包含了一些附加頭信息,其中附加頭信息”Upgrade: WebSocket”表明這是一個申請協議升級的 HTTP 請求,服務器端解析這些附加的頭信息然后產生應答信息返回給客戶端,客戶端和服務器端的 WebSocket 連接就建立起來了,雙方就可以通過這個連接通道自由的傳遞信息,並且這個連接會持續存在直到客戶端或者服務器端的某一方主動的關閉連接。
協議規范:
一個典型的websocket發起請求到響應請求的例子如下
客戶端到服務端: GET / HTTP/1.1 Connection:Upgrade Host:127.0.0.1:8088 Origin:null Sec-WebSocket-Extensions:x-webkit-deflate-frame Sec-WebSocket-Key:puVOuWb7rel6z2AVZBKnfw== Sec-WebSocket-Version:13 Upgrade:websocket 服務端到客戶端: HTTP/1.1 101 Switching Protocols Connection:Upgrade Server:beetle websocket server Upgrade:WebSocket Date:Mon, 26 Nov 2013 23:42:44 GMT Access-Control-Allow-Credentials:true Access-Control-Allow-Headers:content-type Sec-WebSocket-Accept:FCKgUr8c7OsDsLFeJTWrJw6WO8Q=
這是一個握手的http請求,它與普通的http請求有一些區別,首先請求和響應的,”Upgrade:WebSocket”表示請求的目的就是要將客戶端和服務器端的通訊協議從 HTTP 協議升級到 WebSocket 協議。從客戶端到服務器端請求的信息里包含有”Sec-WebSocket-Extensions”、“Sec-WebSocket-Key”這樣的頭信息。這是客戶端瀏覽器需要向服務器端提供的握手信息,服務器端解析這些頭信息,並在握手的過程中依據這些信息生成一個 28 位的安全密鑰並返回給客戶端,以表明服務器端獲取了客戶端的請求,同意創建 WebSocket 連接。
當握手成功后,這個時候tcp連接已在經建立了,客戶發送上來的時候就是純純的數據了。不過服務端要判斷什么時候是一次數據請求的開始,什么時候是請求的結束。在websocket中,由於瀏覽端和服務端已經打好招呼,如我發送的內容為utf-8 編碼,如果我發送0x00,表示包的開始,如果發送了0xFF,就表示包的結束了。這就解決了黏包的問題。
從握手的協議可以看出,如果我們要使用Websocket,我們需要一個實現Websocket協議規范的服務器,這不在我們討論的范圍。
值得一提的是:websocket是可以和http共用監聽端口的,也就是它可以公用端口完成socket任務。
Socket.io
主角終於上場了,聽了上面對Websocket的介紹之后,你是不是想,socket.io就是對Websocket的封裝呢,並且實現了Websocket的服務端代碼。不錯,但是不完全正確。剛才我們說到,在WebSocket沒有出現之前,實現與服務端的實時通訊可以通過輪詢來完成任務.。Socket.io將Websocket和輪詢(Polling)機制以及其它的實時通信方式封裝成了通用的接口,並且在服務端實現了這些實時機制的相應代碼。也就是說,Websocket僅僅是Socket.io實現實時通信的一個子集。
那么,Socket.io都實現了Polling中的那些通信機制呢?
- Adobe® Flash® Socket
- AJAX long polling
- AJAX multipart streaming
- Forever Iframe
- JSONP Polling
Adobe® Flash® Socket 大部分PC瀏覽器都支持的socket模式,不過是通過第三方嵌入到瀏覽器,不在W3C規范內,所以可能將逐步被淘汰,況且,大部分的手機瀏覽器都不支持這種模式。
AJAX long polling 這個很好理解,所有瀏覽器都支持這種方式,就是定時的向服務器發送請求,缺點是會給服務器帶來壓力並且出現信息更新不及時的現象。
AJAX multipart streaming 這是在XMLHttpRequest對象上使用某些瀏覽器(比如說Firefox)支持的multi-part標志。Ajax請求被發送給服務器端並保持打開狀態(掛起狀態),每次需要向客戶端發送信息,就尋找一個掛起的的http請求響應給客戶端,並且所有的響應都會通過統一連接來寫入
var xhr = $.ajaxSettings.xhr(); xhr.multipart =true; xhr.open('GET', 'ajax', true); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { processEvents($.parseJSON(xhr.responseText)); } }; xhr.send(null);
Forever Iframe (永存的Iframe)技術涉及了一個置於頁面中的隱藏Iframe標簽,該標簽的src屬性指向返回服務器端事件的servlet路徑。每次在事件到達時,servlet寫入並刷新一個新的script標簽,該標簽內部帶有JavaScript代碼,iframe的內容被附加上這一script標簽,標簽中的內容就會得到執行。這種方式的缺點是接和數據都是由瀏覽器通過HTML標簽來處理的,因此你沒有辦法知道連接何時在哪一端已被斷開了,並且Iframe標簽在瀏覽器中將被逐步取消使用。
JSONP Polling JSONP輪詢基本上與HTTP輪詢一樣,不同之處則是JSONP可以發出跨域請求,詳細請搜索查詢jsonp的內容。