如今,不少網站爲了實現推送技術,所用的技術都是輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP request,而後由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器須要不斷的向服務器發出請求,然而HTTP request的header是很是長的,裏面包含的數據可能只是一個很小的值,這樣會佔用不少的帶寬和服務器資源。php
而比較新的技術去作輪詢的效果是Comet,使用了AJAX。但這種技術雖然可達到雙向通訊,但依然須要發出請求,並且在Comet中,廣泛採用了長連接,這也會大量消耗服務器帶寬和資源。jquery
用大白話揭開Ajax長輪詢(long polling)的神祕面紗編程
面對這種情況,HTML5定義了WebSocket協議,能更好的節省服務器資源和帶寬並達到實時通信。json
國際慣例,先上維基百科的解釋。segmentfault
"WebSocket是HTML5開始提供的一種在單個 TCP 鏈接上進行全雙工通信的協議。"設計模式
——維基百科瀏覽器
上面是維基百科對WebSocket的解釋,別問我如何解釋上面這段話,由於我也沒看懂,那麼下面我用人話解釋一下吧(僅僅是個人理解):服務器
WebSocket是一個協議,能夠簡單當作是HTTP協議的一個補充協議,WebSocket藉助HTTP協議的基礎完成服務器主動與客戶端實時傳輸數據。
這是WebSocket和HTTP之間的關係,有交集,可是並非所有。
WebSocket只是HTML5其中的一個API(HTML5推出了不少新的API,贊),這個API能夠經過WebSocket協議實現WebSocket技術。
在WebSocket API中,瀏覽器和服務器只須要作一個握手的動做,而後,瀏覽器和服務器之間就造成了一條快速通道。二者之間就直接能夠數據互相傳送。
關鍵點在於如何"握手",只要咱們完成了握手的這個工做,那麼WebScoket技術就算是可以使用了。
前面說了WebSocket與HTTP有交集的,或者能夠說WebSocket藉助了HTTP的基礎就是體如今這裏了,能夠看到圖中的紅點,分別是WebSocket的請求頭和響應頭,一來一回,握手也就完成了,實時鏈接也就創建起來了!
下面講解一下幾個重要的頭參數:
Request: Upgrade:WebSocket; //指定WebSocket協議 Sec-WebSocket-Version: 13 //指定Websocket Draft協議版本 Sec-WebSocket-Key:Cv8RLRCr07Ujlqexqq9Nrw== //驗證key值,由瀏覽器隨機生成,能夠理解爲一個校驗碼 Reponse: Connection:Upgrade ; Upgrade:webSocket;//沒錯我就是webSocket Sec-WebSocket-Accept:rC+mM80welcslAqBHpav4MSDzAU= ;//這是返回頭校驗碼,和請求頭的Key配對 Sec-WebSocket-Version: 13 //指定Websocket Draft協議版本
以上就是一次完成的WebSocket握手,握手完以後就能夠進行實時通訊了。
先上個代碼看看:
本文所用服務端語言爲PHP,其餘語言能夠對照着看,大的原理都同樣:
WebSocket Demo下載連接(代碼實在太長,直接下載吧)
使用方法
Windows下要用cmd啓動server.php文件,Linux同理 而後用瀏覽器訪問index.html Demo是上網找的,不能當作實際用途,簡單看看運行流程就好
代碼須要改的就是index.html的url和server.php的ip。
我講解幾個重要的模塊
server.php:
<?php include 'websocket.class.php'; $config=array( 'address'=>'127.0.0.1', 'port'=>'8000', 'event'=>'WSevent',//回調函數的函數名 'log'=>true, ); $websocket = new websocket($config); $websocket->run();
server.php:經過cmd運行server.php,引用並實例化websocket.class.php類庫,並執行run方法,使其充當一個"服務器",持續掛着這個鏈接,當客戶端有消息就作出對應動做。
Index.html:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>websocket_TEST</title> <script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script> </head> <body> <textarea class="log" style="width: 100%; height: 500px;"> =======websocket====== </textarea> <input type="button" value="鏈接" onClick="link()"> <input type="button" value="斷開" onClick="dis()"> <input type="text" id="text"> <input type="button" value="發送" onClick="send()"> <script> function link(){ var url='ws://127.0.0.1:8000'; socket=new WebSocket(url); socket.onopen=function(){log('鏈接成功')} socket.onmessage=function(msg){log('得到消息:'+msg.data);console.log(msg);} socket.onclose=function(){log('斷開鏈接')} } function dis(){ socket.close(); socket=null; } function log(var1){ $('.log').append(var1+"\r\n"); } function send(){ socket.send($('#text').attr('value')); } function send2(){ var json = JSON.stringify({'type':'php','msg':$('#text2').attr('value')}) socket.send(json); } </script> </body> </html>
Index.html:HTML5提供了WebSocket API,因此,客戶端實例化此API,參數爲IP:端口,鏈接上服務端的WebSocket鏈接。
function roboot()
<? function roboot($sign,$t){ global $websocket; switch ($t) { case 'hello': $show='hello,GIt @ OSC'; break; case 'name': $show='Robot'; break; case 'time': $show='當前時間:'.date('Y-m-d H:i:s'); break; case '再見': $show='( ^_^ )/~~拜拜'; $websocket->write($sign,'Robot:'.$show); $websocket->close($sign); return; break; case '天王蓋地虎': $array = array('小雞燉蘑菇','寶塔震河妖','粒粒皆辛苦'); $show = $array[rand(0,2)]; break; default: $show='( ⊙o⊙?)不懂,你能夠嘗試說:hello,name,time,再見,天王蓋地虎.'; } $websocket->write($sign,'Robot:'.$show); }
function roboot():指定了客戶端的操做和服務端回覆的信息,客戶端發送' 天王蓋地虎',服務端返回信息' 小雞燉蘑菇'/' 寶塔震河妖'/' 粒粒皆辛苦'。
文章最後來個小科普:
關於Socket 與 WebScoket
Socket 其實並非一個協議。它工做在 OSI 模型會話層(第5層),是爲了方便你們直接使用更底層協議(通常是 TCP 或 UDP )而存在的一個抽象層。
最先的一套 Socket API 是 Berkeley sockets ,採用 C 語言實現。它是 Socket 的事實標準,POSIX sockets 是基於它構建的,多種編程語言都遵循這套 API,在 JAVA、Python 中都能看到這套 API 的影子。
下面摘錄一段更容易理解的文字(來自 http和socket之長鏈接和短鏈接區別):
Socket是應用層與TCP/IP協議族通訊的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來講,一組簡單的接口就是所有,讓Socket去組織數據,以符合指定的協議。
主機 A 的應用程序要能和主機 B 的應用程序通訊,必須經過 Socket 創建鏈接,而創建 Socket 鏈接必須須要底層 TCP/IP 協議來創建 TCP 鏈接。創建 TCP 鏈接須要底層 IP 協議來尋址網絡中的主機。咱們知道網絡層使用的 IP 協議能夠幫助咱們根據 IP 地址來找到目標主機,可是一臺主機上可能運行着多個應用程序,如何才能與指定的應用程序通訊就要經過 TCP 或 UPD 的地址也就是端口號來指定。這樣就能夠經過一個 Socket 實例惟一表明一個主機上的一個應用程序的通訊鏈路了。
而 WebSocket 則不一樣,它是一個完整的 應用層協議,包含一套標準的 API 。
因此,從使用上來講,WebSocket 更易用,而 Socket 更靈活。
再簡單來講, Socket是一個應用程序接口,是抽象的,WebSocket和HTTP是具體實現,
參考文章:
https://www.zhihu.com/question/20215561 《 知乎回答:什麼是WebSocket?》
https://zh.wikipedia.org/wiki/WebSocket 《維基百科:WebSocket》
http://zengrong.net/post/2199.htm 《zrong's blog》