WebSocket是什嗎?
WebSocket是一個持久化的協議,這是相對於http非持久化來說的。舉個簡單的例子,http1.0的生命週期是以request作為界定的,也就是一個request,一個response,對於http來說,本次client與server的會話到此結束;而在http1.1中,稍微有所改進,即添加了keep-alive,也就是在一個http串連中可以進行多個request請求和多個response接受操作。然而在即時通訊中,並沒有多大的作用,http只能由client發起請求,server才能返回資訊,即server不能主動向client推送資訊,無法滿足即時通訊的要求。而WebSocket可以進行持久化串連,即client只需進行一次握手,成功後即可持續進行資料通訊,值得關注的是WebSocket實現client與server之間全雙工系統通訊,即server端有資料更新時可以主動推送給client端。
下面的圖示範了 client 和 server 之間建立 websocket 串連時握手部分,這個部分在 node 中可以十分輕鬆的完成,因為 node 提供的 net 模組已經對 socket 通訊端做了封裝處理,開發人員使用的時候只需要考慮資料的互動而不用處理串連的建立。
client與server建立socket時握手的會話內容,即request與response
a、client建立WebSocket時向伺服器端請求的資訊
GET /chat HTTP/1.1Host: server.example.comUpgrade: websocket //告訴伺服器現在發送的是WebSocket協議Connection: UpgradeSec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== //是一個Base64 encode的值,這個是瀏覽器隨機產生的,用於驗證伺服器端返回資料是否是WebSocket助理Sec-WebSocket-Protocol: chat, superchatSec-WebSocket-Version: 13Origin: php.cn
b、伺服器擷取到client請求的資訊後,根據WebSocket協議對資料進行處理並返回,其中要對Sec-WebSocket-Key進行加密等操作
HTTP/1.1 101 Switching ProtocolsUpgrade: websocket //依然是固定的,告訴用戶端即將升級的是Websocket協議,而不是mozillasocket,lurnarsocket或者shitsocketConnection: UpgradeSec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= //這個則是經過伺服器確認,並且加密過後的 Sec-WebSocket-Key,也就是client要求建立WebSocket驗證的憑證Sec-WebSocket-Protocol: chat
PHP中建立socket的過程講解
1、在PHP中,client與server之間建立socket通訊,首先在PHP中建立socket並監聽連接埠資訊,代碼如下:
<?php//傳相應的IP與連接埠進行建立socket操作function WebSocket($address,$port){$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);//1表示接受所有的資料包socket_bind($server, $address, $port);socket_listen($server);return $server;}?>
2、設計一個迴圈掛起WebSocket通道,進行資料的接收、處理和發送
<?php//對建立的socket迴圈進行監聽,處理資料 function run(){ //死迴圈,直到socket斷開 while(true){ $changes=$this->sockets; $write=NULL; $except=NULL; /* //這個函數是同時接受多個串連的關鍵,我的理解它是為了阻塞程式繼續往下執行。 socket_select ($sockets, $write = NULL, $except = NULL, NULL); $sockets可以理解為一個數組,這個數組中存放的是檔案描述符。當它有變化(就是有新訊息到或者有用戶端串連/斷開)時,socket_select函數才會返回,繼續往下執行。 $write是監聽是否有用戶端寫資料,傳入NULL是不關心是否有寫變化。 $except是$sockets裡面要被排除的元素,傳入NULL是”監聽”全部。 最後一個參數是逾時時間 如果為0:則立即結束 如果為n>1: 則最多在n秒後結束,如遇某一個串連有新動態,則提前返回 如果為null:如遇某一個串連有新動態,則返回 */ socket_select($changes,$write,$except,NULL); foreach($changes as $sock){ //如果有新的client串連進來,則 if($sock==$this->master){ //接受一個socket串連 $client=socket_accept($this->master); //給新串連進來的socket一個唯一的ID $key=uniqid(); $this->sockets[]=$client; //將新串連進來的socket存進串連池 $this->users[$key]=array( 'socket'=>$client, //記錄新串連進來client的socket資訊 'shou'=>false //標誌該socket資源沒有完成握手 ); //否則1.為client斷開socket串連,2.client發送資訊 }else{ $len=0; $buffer=''; //讀取該socket的資訊,注意:第二個參數是引用傳參即接收資料,第三個參數是接收資料的長度 do{ $l=socket_recv($sock,$buf,1000,0); $len+=$l; $buffer.=$buf; }while($l==1000); //根據socket在user池裡面尋找相應的$k,即健ID $k=$this->search($sock); //如果接收的資訊長度小於7,則該client的socket為中斷連線 if($len<7){ //給該client的socket進行斷開操作,並在$this->sockets和$this->users裡面進行刪除 $this->send2($k); continue; } //判斷該socket是否已經握手 if(!$this->users[$k]['shou']){ //如果沒有握手,則進行握手處理 $this->woshou($k,$buffer); }else{ //走到這裡就是該client發送資訊了,對接受到的資訊進行uncode處理 $buffer = $this->uncode($buffer,$k); if($buffer==false){ continue; } //如果不為空白,則進行訊息推送操作 $this->send($k,$buffer); } } } }}?>
3、以上伺服器端完成的WebSocket的前期工作後,就等著client串連進行,client建立WebSocket很簡單,代碼如下:
var ws = new WebSocket("ws://IP:連接埠");//握手監聽函數ws.onopen=function(){ //狀態為1證明握手成功,然後把client自訂的名字發送過去 if(so.readyState==1){ //握手成功後對伺服器發送資訊 so.send('type=add&ming='+n); }}//錯誤返回資訊函數ws.onerror = function(){ console.log("error");};//監聽伺服器端推送的訊息ws.onmessage = function (msg){ console.log(msg);}//斷開WebSocket串連ws.onclose = function(){ ws = false;}
【相關教程推薦】
1. 《php.cn獨孤九賤(4)-php視頻教程》
2. php編程從入門到精通全套教程