WebSocket協(xié)議
目前Workerman的WebSocke協(xié)議版本為13。
WebSocket protocol 是HTML5一種新的協(xié)議。它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工通信。
WebSocket與TCP關(guān)系
WebSocket和HTTP一樣是一種應(yīng)用層協(xié)議,都是基于TCP傳輸?shù)?,WebSocket本身和Socket并沒(méi)有多大關(guān)系,更不能等同。
WebSocket協(xié)議握手
WebSocket協(xié)議有一個(gè)握手的過(guò)程,握手時(shí)瀏覽器和服務(wù)端是以HTTP協(xié)議通信的,在Workerman中可以這樣介入到握手過(guò)程。
當(dāng) workerman <= 4.1 時(shí)
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Connection\TcpConnection;
use Workerman\Worker;
$ws = new Worker('websocket://0.0.0.0:8181');
$ws->onConnect = function($connection)
{
$connection->onWebSocketConnect = function($connection , $httpBuffer)
{
// 可以在這里判斷連接來(lái)源是否合法,不合法就關(guān)掉連接
// $_SERVER['HTTP_ORIGIN']標(biāo)識(shí)來(lái)自哪個(gè)站點(diǎn)的頁(yè)面發(fā)起的websocket連接
if($_SERVER['HTTP_ORIGIN'] != 'http://wtbis.cn')
{
$connection->close();
}
// onWebSocketConnect 里面$_GET $_SERVER是可用的
// var_dump($_GET, $_SERVER);
};
};
Worker::runAll();
當(dāng) workerman >= 5.0 時(shí)
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;
$worker = new Worker('websocket://0.0.0.0:12345');
$worker->onWebSocketConnect = function (TcpConnection $connection, Request $request) {
if ($request->header('origin') != 'http://wtbis.cn') {
$connection->close();
}
var_dump($request->get());
var_dump($request->header());
};
Worker::runAll();
WebSocket協(xié)議傳輸二進(jìn)制數(shù)據(jù)
websocket協(xié)議默認(rèn)只能傳輸utf8文本,如果要傳輸二進(jìn)制數(shù)據(jù),請(qǐng)閱讀以下部分。
websocket協(xié)議中在協(xié)議頭中使用一個(gè)標(biāo)記位來(lái)標(biāo)記傳輸?shù)氖嵌M(jìn)制數(shù)據(jù)還是utf8文本數(shù)據(jù),瀏覽器會(huì)驗(yàn)證標(biāo)記和傳輸?shù)膬?nèi)容類(lèi)型是否符合,如果不符合則會(huì)報(bào)錯(cuò)斷開(kāi)連接。
所以服務(wù)端發(fā)送數(shù)據(jù)的時(shí)候需要根據(jù)傳輸?shù)臄?shù)據(jù)類(lèi)型設(shè)置這個(gè)標(biāo)記位,在Workerman中如果是普通utf8文本,則需要設(shè)置(默認(rèn)就是此值,一般不用再手動(dòng)設(shè)置)
use Workerman\Protocols\Websocket;
$connection->websocketType = Websocket::BINARY_TYPE_BLOB;
如果是二進(jìn)制數(shù)據(jù),則需要設(shè)置
use Workerman\Protocols\Websocket;
$connection->websocketType = Websocket::BINARY_TYPE_ARRAYBUFFER;
注意:如果沒(méi)設(shè)置$connection->websocketType,則$connection->websocketType默認(rèn)為BINARY_TYPE_BLOB(也就是utf8文本類(lèi)型)。一般應(yīng)用傳輸?shù)亩际莡tf8文本,例如傳輸?shù)氖莏son數(shù)據(jù),所以不用手動(dòng)設(shè)置$connection->websocketType。只有在傳輸二進(jìn)制數(shù)據(jù)時(shí)(例如圖片數(shù)據(jù)、protobuffer數(shù)據(jù)等)才要設(shè)置此屬性為BINARY_TYPE_ARRAYBUFFER。
把workerman作為Websocket客戶(hù)端
可以利用AsyncTcpConnection類(lèi)配合ws協(xié)議讓workerman作為websocket客戶(hù)端連接遠(yuǎn)程websocket服務(wù)端,完成雙向?qū)崟r(shí)通訊。