Swoole從入門到入土(17)——WebSocket服務器[成員函數與配置選項]

這一節,咱們重點了解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 子協議。

相關文章
相關標籤/搜索