web聊天室場景,為了獲取最新的信息,有兩種處理方法:
- ajax: 定時向服務端拉取最新的信息。不足之處在於浪費資源,而且存在延時
- commet: 頁面利用iframe,由服務端推送消息到客戶端
而websocket協議的出現是完善web雙向通信的不足,它通過身份驗證成功後,雙方保持連接實現雙向通信操作。
從websocket的字面意義,就能看得出它跟web的聯繫
1、通信協議
1.1、通信交互圖
1.2、協議格式
協議標識(1字節)+報頭(1字節)+pack(2字節|8字節)+掩碼(4字節)+data
<125 則pack不存在
>125 and < 127 則pack為2字節
>127 則8字節
1.3、掩碼區別
客戶端: 為安全考慮,需加上掩碼;
而服務端: 則不用
1.4、報頭計算方式
客戶端->服務端:
客戶端發送: 128與數據長度進行或運算、然後調用chr方法獲取對應ascii
服務端接收: 調用ord方法獲取對應ascii碼值,然後與127進行且運算
服務端->客戶端:
服務端發送: 調用調用chr方法獲取對應ascii
客戶端接收: 調用ord方法獲取對應ascii碼值
2、websocket類
實現ProtocolInterface接口
2.1、類概要
2.2、核心方法解析
- input靜態方法
- 根據協議格式,判斷當前長度是否小於6個字節,如是則返回0.相反則繼續運行
- 判斷是否已握手
-- 沒握手則調用dealHandshake()方法
處理websocket握手問題: 此握手是通過http協議的get方式完成。其在請求頭部中增加密鑰信息
-- 進行正則匹配,獲取Sec-WebSocket-Key的值
-- 計算base64_encode(sha1($Sec_WebSocket_Key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
-- 構造http響應報文
-- 設置此鏈接$connection,關於websocket的屬性信息
-- 調用consumeRecvBuffer()方法,去掉此次報文中的握手信息
-- 判斷此次鏈接中是否存在onWebSocketConnect回調方法,如存在則調用parseHttpHeader()方法,進行解析此次握手報文的http信息,得到對應的全局變量$_GET = $_SERVER = $_SESSION = $_COOKIE,再執行回調方法
-- 往客戶端發送http響應報文
-- 已握手
則按照協議格式進行計算
- encode靜態方法
- 計算數據長度,與數值125/126/127進行判斷:
-- 為125,協議標識+報頭+數據內容
-- 為126,協議標識+報頭+pack(2字節)+數據內容
-- 為127,協議標識+報頭+pack(8字節)+數據內容
- 進行封包
- decode靜態方法
- 獲取報頭內容,調用ord方法獲取對應ascii碼值,然後與127進行且運算得到數值
- 數值與125/126/127進行判斷,得到對應的掩碼和數據
- 遍歷數據,使得每位數據與掩碼進行按位異或,並得到最終內容
閱讀更多 iamasb 的文章