這一節,咱們重點了解websocket server的成員函數以及相關的配置選項。php
一、成員函數web
push:向 WebSocket 客戶端鏈接推送數據,長度最大不得超過 2M。編程
Swoole\WebSocket\Server->push(int $fd, string $data, int $opcode = WEBSOCKET_OPCODE_TEXT, bool $finish = true): bool // v4.4.12版本改成了flags參數 Swoole\WebSocket\Server->push(int $fd, string $data, int $opcode = WEBSOCKET_OPCODE_TEXT, int $flags = SWOOLE_WEBSOCKET_FLAG_FIN): bool
$fd:客戶端鏈接的 ID 【若是指定的 $fd 對應的 TCP 鏈接並不是 WebSocket 客戶端,將會發送失敗】websocket
$data:要發送的數據內容,Swoole 版本 >= v4.2.0 傳入的 $data,若是是 Swoole\WebSocket\Frame 對象則其後續參數會被忽略swoole
$opcode:指定發送數據內容的格式 【默認爲WEBSOCKET_OPCODE_TEXT。發送二進制內容 $opcode 參數須要設置爲 WEBSOCKET_OPCODE_BINARY】socket
$finish:是否發送完成函數
注意:學習
自 v4.4.12 版本起,finish 參數(bool 型)改成 flags 參數(int 型)以支持 WebSocket 壓縮,finish 對應 SWOOLE_WEBSOCKET_FLAG_FIN 值爲 1,原有 bool 型值會隱式轉換爲 int 型,此改動向下兼容無影響。 此外壓縮 flag 爲 SWOOLE_WEBSOCKET_FLAG_COMPRESS。spa
exist:判斷 WebSocket 客戶端是否存在,而且狀態爲 Active 狀態。設計
Swoole\WebSocket\Server->exist(int $fd): bool
返回值:鏈接存在,而且已完成 WebSocket 握手,返回 true;鏈接不存在或還沒有完成握手,返回 false
注意:v4.3.0 之後,此 API 僅用於判斷鏈接是否存在,請使用 isEstablished 判斷是否爲 WebSocket 鏈接。
pack:打包 WebSocket 消息。
Swoole\WebSocket\Server::pack(string $data, int $opcode = WEBSOCKET_OPCODE_TEXT, bool $finish = true, bool $mask = false): string // v4.4.12版本改成了flags參數 Swoole\WebSocket\Server::pack(string $data, int $opcode = WEBSOCKET_OPCODE_TEXT, int $flags = SWOOLE_WEBSOCKET_FLAG_FIN): string
$data:消息內容
$opcode:指定發送數據內容的格式 【默認爲WEBSOCKET_OPCODE_TEXT。發送二進制內容 $opcode 參數須要設置爲 WEBSOCKET_OPCODE_BINARY】
$finish:幀是否完成 。自 v4.4.12 版本起,finish 參數(bool 型)改成 flags 參數(int 型)以支持 WebSocket 壓縮,finish 對應 SWOOLE_WEBSOCKET_FLAG_FIN 值爲 1,原有 bool 型值會隱式轉換爲 int 型,此改動向下兼容無影響。
$mask:是否設置掩碼【v4.4.12 已移除此參數】
返回值:返回打包好的 WebSocket 數據包,可經過 Swoole\Server 基類的 send() 發送給對端
$ws = new Swoole\Server('127.0.0.1', 9501 , SWOOLE_BASE); $ws->set(array( 'log_file' => '/dev/null' )); $ws->on('WorkerStart', function (\Swoole\Server $serv) { }); $ws->on('receive', function ($serv, $fd, $threadId, $data) { $sendData = "HTTP/1.1 101 Switching Protocols\r\n"; $sendData .= "Upgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: IFpdKwYy9wdo4gTldFLHFh3xQE0=\r\n"; $sendData .= "Sec-WebSocket-Version: 13\r\nServer: swoole-http-server\r\n\r\n"; $sendData .= Swoole\WebSocket\Server::pack("hello world\n"); $serv->send($fd, $sendData); }); $ws->start();
unpack:解析 WebSocket 數據幀。
Swoole\WebSocket\Server::unpack(string $data): Swoole\WebSocket\Frame|false;
$data:消息內容
返回值:解析失敗返回 false,解析成功返回 Swoole\WebSocket\Frame 對象
disconnect:主動向 WebSocket 客戶端發送關閉幀並關閉該鏈接。
Swoole\WebSocket\Server->disconnect(int $fd, int $code = SWOOLE_WEBSOCKET_CLOSE_NORMAL, string $reason = ''): bool
$fd:客戶端鏈接的 ID【若是指定的 $fd 對應的 TCP 鏈接並不是 WebSocket 客戶端,將會發送失敗】
$code:關閉鏈接的狀態碼【根據 RFC6455
,對於應用程序關閉鏈接狀態碼,取值範圍爲 1000
或 4000-4999
之間】
$reason:關閉鏈接的緣由【utf-8 格式字符串,字節長度不超過 125】
返回值:發送成功返回 true,發送失敗或狀態碼非法時返回 false
注意:Swoole 版本 >= v4.0.3 可用
isEstablished:檢查鏈接是否爲有效的 WebSocket 客戶端鏈接。此函數與 exist 方法不一樣,exist 方法僅判斷是否爲 TCP 鏈接,沒法判斷是否爲已完成握手的 WebSocket 客戶端。
Swoole\WebSocket\Server->isEstablished(int $fd): bool
$fd:客戶端鏈接的 ID【若是指定的 $fd 對應的 TCP 鏈接並不是 WebSocket 客戶端,將會發送失敗】
二、配置選項
WebSocket\Server 是 Server 的子類,可使用 Server->set() 方法傳入配置選項,設置配置選項參數。
· websocket_subprotocol:設置 WebSocket 子協議。設置後握手響應的 HTTP 頭會增長 Sec-WebSocket-Protocol: {$websocket_subprotocol}。
示例代碼:
$server->set([ 'websocket_subprotocol' => 'chat', ]);
· open_websocket_close_frame:啓用 WebSocket 協議中關閉幀(opcode 爲 0x08 的幀)在 onMessage 回調中接收,默認爲 false。開啓後,可在 Swoole\WebSocket\Server 中的 onMessage 回調中接收到客戶端或服務端發送的關閉幀,開發者可自行對其進行處理。
示例代碼:
$server = new Swoole\WebSocket\Server("0.0.0.0", 9501); $server->set(array("open_websocket_close_frame" => true)); $server->on('open', function (Swoole\WebSocket\Server $server, $request) { }); $server->on('message', function (Swoole\WebSocket\Server $server, $frame) { if ($frame->opcode == 0x08) { echo "Close frame received: Code {$frame->code} Reason {$frame->reason}\n"; } else { echo "Message received: {$frame->data}\n"; } }); $server->on('close', function ($ser, $fd) { }); $server->start();
· open_websocket_ping_frame:啓用 WebSocket 協議中 Ping 幀(opcode 爲 0x09 的幀)在 onMessage 回調中接收,默認爲 false。開啓後,可在 Swoole\WebSocket\Server 中的 onMessage 回調中接收到客戶端或服務端發送的 Ping 幀,開發者可自行對其進行處理。值爲 false 時底層會自動回覆 Pong 幀,但若是設爲 true 後則須要開發者自行回覆 Pong 幀。Swoole 版本 >= v4.5.4 可用。
$server = new Swoole\WebSocket\Server("0.0.0.0", 9501); $server->set(array("open_websocket_ping_frame" => true)); $server->on('open', function (Swoole\WebSocket\Server $server, $request) { }); $server->on('message', function (Swoole\WebSocket\Server $server, $frame) { if ($frame->opcode == 0x09) { echo "Ping frame received: Code {$frame->opcode}\n"; // 回覆 Pong 幀 $pongFrame = new Swoole\WebSocket\Frame; $pongFrame->opcode = WEBSOCKET_OPCODE_PONG; $server->push($frame->fd, $pongFrame); } else { echo "Message received: {$frame->data}\n"; } }); $server->on('close', function ($ser, $fd) { }); $server->start();
· open_websocket_pong_frame:啓用 WebSocket 協議中 Pong 幀(opcode 爲 0x0A 的幀)在 onMessage 回調中接收,默認爲 false。開啓後,可在 Swoole\WebSocket\Server 中的 onMessage 回調中接收到客戶端或服務端發送的 Pong 幀,開發者可自行對其進行處理。Swoole 版本 >= v4.5.4 可用
示例代碼:
$server = new Swoole\WebSocket\Server("0.0.0.0", 9501); $server->set(array("open_websocket_pong_frame" => true)); $server->on('open', function (Swoole\WebSocket\Server $server, $request) { }); $server->on('message', function (Swoole\WebSocket\Server $server, $frame) { if ($frame->opcode == 0xa) { echo "Pong frame received: Code {$frame->opcode}\n"; } else { echo "Message received: {$frame->data}\n"; } }); $server->on('close', function ($ser, $fd) { }); $server->start();
· websocket_compression:啓用數據壓縮。爲 true 時容許對幀進行 zlib 壓縮,具體是否可以壓縮取決於客戶端是否可以處理壓縮(根據握手信息決定,參見 RFC-7692) 須要配合 flags 參數 SWOOLE_WEBSOCKET_FLAG_COMPRESS 來真正地對具體的某個幀進行壓縮。Swoole 版本 >= v4.4.12 可用
use Swoole\WebSocket\Frame; use Swoole\WebSocket\Server; $server = new Server('127.0.0.1', 9501); $server->set(['websocket_compression' => true]); $server->on('message', function (Server $server, Frame $frame) { $server->push( $frame->fd, 'Hello Swoole', SWOOLE_WEBSOCKET_OPCODE_TEXT, SWOOLE_WEBSOCKET_FLAG_FIN | SWOOLE_WEBSOCKET_FLAG_COMPRESS ); // $server->push($frame->fd, $frame); // 或者 服務端能夠直接原封不動轉發客戶端的幀對象 }); $server->start();
--------------------------- 我是可愛的分割線 ----------------------------
最後博主借地宣傳一下,漳州編程小組招新了,這是一個面向漳州青少年信息學/軟件設計的學習小組,有意向的同窗點擊連接,聯繫我吧
設置 WebSocket 子協議。