php使用websocket示例詳解

2021-07-03 08:55:15 字數 4587 閱讀 6595

**url:

下面我畫了乙個圖演示 client 和 server 之間建立 websocket 連線時握手部分,這個部分在 node 中可以十分輕鬆的完成,因為 node 提供的 net 模組已經對 socket 套接字做了封裝處理,開發者使用的時候只需要考慮資料的互動而不用處理連線的建立。而 php 沒有,從 socket 的連線、建立、繫結、監聽等,這些都需要我們自己去操作,所以有必要拿出來再說一說。

① 和 ② 實際上就是乙個 http 的請求和響應,只不過我們在處理的過程中我們拿到的是沒有經過解析的字串。如:

複製**

**如下:

我們往常看到的請求是這個樣子,當這東西到了伺服器端,我們可以通過一些**庫直接拿到這些資訊。

一、php 中處理 websocket

websocket 連線是由客戶端主動發起的,所以一切要從客戶端出發。第一步是要解析拿到客戶端發過來的 sec-websocket-key 字串。

複製**

**如下:

client 請求的格式

首先 php 建立乙個 socket 連線,監聽埠的資訊。

1. socket 連線的建立

關於 socket 套接字的建立,相信很多大學修過計算機網路的人都知道了,下面是一張連線建立的過程:

複製**

**如下:

// 建立乙個 socket 套接字

$master = socket_create(af_inet, sock_stream, sol_tcp);

socket_set_option($master, sol_socket, so_reuseaddr, 1);

socket_bind($master, $address, $port);

socket_listen($master);

相比 node,這個地方的處理實在是太麻煩了,上面幾行**並未建立連線,只不過這些**是建立乙個 socket 套接字必須要寫的東西。由於處理過程稍微有複雜,所以我把各種處理寫進了乙個類中,方便管理和呼叫。

複製**

**如下:

class ws else

} else else }}

}}}

上面這段**是經過我除錯了的,沒太大的問題,如果想測試的話,可以在 cmd 命令列中鍵入 php /path/to/demo.php;當然,上面只是乙個類,如果要測試的話,還得新建乙個例項。

複製**

**如下:

$ws = new ws('localhost', 4000);

客戶端**可以稍微簡單點:

複製**

**如下:

var ws = new websocket("ws://localhost:4000");

ws.onopen = function();

ws.onerror = function();

執行伺服器**,當客戶端連線的時候,我們可以看到:

2. 提取 sec-websocket-key 資訊

複製**

**如下:

function getkey($req)

return $key; }

這裡比較簡單,直接正則匹配,websocket 資訊頭一定包含 sec-websocket-key,所以我們匹配起來也比較快捷~

3. 加密 sec-websocket-key

複製**

**如下:

function encry($req)

將 sha-1 加密後的字串再進行一次 base64 加密。如果加密演算法錯誤,客戶端在進行校檢的時候會直接報錯:

4. 應答 sec-websocket-accept

複製**

**如下:

function dohandshake($socket, $req)

這裡千萬要注意,每乙個請求和相應的格式,最後有乙個空行,也就是 \r\n,開始測試的時候把這東西給弄丟了,糾結了半天。

當客戶端成功校檢key後,會觸發 onopen 函式:

5. 資料幀處理

複製**

**如下:

// 解析資料幀

function decode($buffer)  else if ($len === 127)  else 

for ($index = 0; $index < strlen($data); $index++)

return $decoded;}

這裡涉及的編碼問題在前文中已經提到過了,這裡就不贅述,php 對字元處理的函式太多了,也記得不是特別清楚,這裡就沒有詳細的介紹解碼程式,直接把客戶端傳送的資料原樣返回,可以算是乙個聊天室的模式吧。

複製**

**如下:

// 返回幀資訊處理

function frame($s)

$ns = "";

foreach ($a as $o)

return $ns; }

// 返回資料

function send($client, $msg)

客戶端**:

複製**

**如下:

var ws = new websocket("ws://localhost:4000");

ws.onopen = function();

ws.onmessage = function(e);

ws.onerror = function();

ws.send("李靖");

在連通之後傳送資料,伺服器原樣返回:

二、注意問題

1. websocket 版本問題

客戶端在握手時的請求中有sec-websocket-version: 13,這樣的版本標識,這個是乙個公升級版本,現在的瀏覽器都是使用的這個版本。而以前的版本在資料加密的部分更加麻煩,它會傳送兩個key:

複製**

**如下:

如果是這種版本(比較老,已經沒在使用了),需要通過下面的方式獲取

複製**

**如下:

function encry($key1,$key2,$l8b)

//some math

$key1_sec = pack("n",$key1_num / $key1_spc);

$key2_sec = pack("n",$key2_num / $key2_spc);

return md5($key1_sec.$key2_sec.$l8b,1);}

只能無限吐槽這種驗證方式!相比 nodejs 的 websocket 操作方式:

複製**

**如下:

//伺服器程式

var crypto = require('crypto');

var ws = '258eafa5-e914-47da-95ca-c5ab0dc85b11';

require('net').createserver(function(o)else;

});}).listen(8000);

2. 資料幀解析**

本文沒有給出 decodeframe 這樣資料幀解析**,前文中給出了資料幀的格式,解析純屬體力活。

PHP實現websocket通訊的方法示例

執行方法 首先先修改server.php與index.html的ip 通過命令列執行 php路徑 php.exe 檔案路徑 server.php 然後通過瀏覽器開啟index.html server.php config array address 192.168.0.200 port 8000 e...

ConcurrentHashMap使用示例

concurrenthashmap是併發效率更高的map,用來替換其他執行緒安全的map容器,比如hashtable和collections.synchronizedmap。實際上,併發執行時,執行緒安全的容器只能保證自身的資料不被破壞,但無法保證業務的行為是否正確。錯誤的理解這裡的執行緒安全,不恰...

webSocket 基本使用

安裝 websocketnpm i ws建立物件const websocket require ws const wss newwebsocket.srever 監聽事件 連線事件 wss.on connection client 接收資料事件 wss.on connection client 傳送...