簡單又好用的聊天室技術——WebSocket

如今,不少網站爲了實現推送技術,所用的技術都是輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP request,而後由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器須要不斷的向服務器發出請求,然而HTTP request的header是很是長的,裏面包含的數據可能只是一個很小的值,這樣會佔用不少的帶寬和服務器資源。php

Ajax輪詢——「定時的經過Ajax查詢服務端"html

而比較新的技術去作輪詢的效果是Comet,使用了AJAX。但這種技術雖然可達到雙向通訊,但依然須要發出請求,並且在Comet中,廣泛採用了長連接,這也會大量消耗服務器帶寬和資源。jquery

Comet——隨着AJAX技術興起而產生的新技術web

用大白話揭開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是上網找的,不能當作實際用途,簡單看看運行流程就好

bVve8J

代碼須要改的就是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》

相關文章
相關標籤/搜索