WebSocketプロトコル
現在のWorkermanのWebSocketプロトコルバージョンは13です。
WebSocketプロトコルはHTML5の新しいプロトコルです。これにより、ブラウザとサーバー間での全二重通信が実現されます。
WebSocketとTCPの関係
WebSocketはHTTPと同様にアプリケーション層のプロトコルであり、どちらもTCPに基づいて伝送されます。WebSocket自体はSocketとはあまり関係がなく、同じものとして考えるべきではありません。
WebSocketプロトコルのハンドシェイク
WebSocketプロトコルにはハンドシェイクのプロセスがあり、ハンドシェイク時にはブラウザとサーバーがHTTPプロトコルを使用して通信します。Workermanでは、以下の方法でハンドシェイクプロセスに介入することができます。
Workermanが <= 4.1 の場合
<?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)
{
// ここで接続元が合法かどうかを判断できます。 不合法の場合は接続を閉じます。
// $_SERVER['HTTP_ORIGIN']はどのサイトからWebSocket接続が発起されたかを示します。
if($_SERVER['HTTP_ORIGIN'] != 'https://www.workerman.net')
{
$connection->close();
}
// onWebSocketConnect内では$_GETと$_SERVERが使用できます。
// var_dump($_GET, $_SERVER);
};
};
Worker::runAll();
Workermanが >= 5.0 の場合
<?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') != 'https://www.workerman.net') {
$connection->close();
}
var_dump($request->get());
var_dump($request->header());
};
Worker::runAll();
WebSocketプロトコルによるバイナリデータの送信
WebSocketプロトコルはデフォルトでutf8テキストのみを送信できます。バイナリデータを送信する場合は、以下の部分を読んでください。
WebSocketプロトコルでは、プロトコルヘッダ内にバイナリデータかutf8テキストデータかを示すフラグが使用されます。ブラウザは、フラグと送信されるコンテンツのタイプが一致するかを検証し、一致しない場合はエラーが発生し接続が切断されます。
そのため、サーバーがデータを送信する際には、送信するデータのタイプに応じてこのフラグを設定する必要があります。Workermanでは、通常のutf8テキストの場合、次のように設定します(デフォルトでこの値なので、手動で設定する必要はありません)。
use Workerman\Protocols\Websocket;
$connection->websocketType = Websocket::BINARY_TYPE_BLOB;
もしバイナリデータの場合は、次のように設定します。
use Workerman\Protocols\Websocket;
$connection->websocketType = Websocket::BINARY_TYPE_ARRAYBUFFER;
注意:もし$connection->websocketTypeが設定されていない場合、$connection->websocketTypeはデフォルトでBINARY_TYPE_BLOB(すなわちutf8テキストタイプ)となります。一般的なアプリケーションが送信するのはutf8テキストであり、例えばjsonデータを送信する場合が多いため、通常は$connection->websocketTypeを手動で設定する必要はありません。バイナリデータを送信する場合(例えば画像データやprotobufferデータなど)のみ、プロパティをBINARY_TYPE_ARRAYBUFFERに設定する必要があります。
WorkermanをWebSocketクライアントとして利用する
AsyncTcpConnectionクラスを利用してwsプロトコルを使うことで、WorkermanをWebSocketクライアントとしてリモートWebSocketサーバーに接続し、双方向リアルタイム通信を実現できます。