Wiz テックブログ

Wizは、最新のIoTやICTサービスをお客様に届ける「ITの総合商社」です。

LaravelでWebSocket(Ratchet)を使ってみた

https://image.slidesharecdn.com/asyncphpdrupalcampla-140908080505-phpapp02/95/asynchronous-php-and-realtime-messaging-39-638.jpg?cb=1410262331

こんにちは。バックエンドエンジニアの米山です。

今回開発案件で、WebSocketを使ったシステム開発に携わることになったので、導入時のメモや困ったことetc...を書いていこうと思います。

まず、WebSocketとは?

Socketを使った技術は、古くからJavaなどの世界で存在していましたが、WebSocketはこれをインターネット上で可能にしたものです。

【従来のWeb通信】

https://create-it-myself.com/wp-content/uploads/study-websoket-spec-image1-768x536.png

従来のWeb通信は「1回のリクエスト」に「1回のレスポンス」で処理を行なっていました。

キャッチボールをイメージしてもらえたら良いと思います。

【WebSocketによる通信】

https://create-it-myself.com/wp-content/uploads/study-websoket-spec-image7-768x535.png

これがWebSocketになると「双方向通信」となり、ソケットが開いている間は任意のタイミングでクライアント<-->サーバ間通信が行えます。

WebSocketを導入するために

今回実施した開発案件では、以下の環境・条件で構成を考えました。

  • サーバ側の開発言語はPHP(Laravel)であること
  • フロントエンド側にサーバ側の言語仕様を押し付けないこと
    • PHP(Laravel)の設計思想や概念に依存するコードをフロント側に強要しない。フロントはフロントで技術選定できる環境にする。
  • なるべく、サードパーティ製のツール(firebase等)を使わず、リアルタイム性を実現できること

以上のことから、今回は「Ratchet」というライブラリを選択しました。

LaravelでWebSocketを構築しようとすると、必ずと言っていいほど「Laravel-Echo」が検索ヒットします。

しかし上記に挙げた条件の通り、フロントエンドはフロントエンドで技術選定を行いコーディングするので、依存しないRatchetを選びました。

早速Ratchetを導入!

では、LaravelプロジェクトにRatchetを導入してみましょう。

LaravelではComposerを使ったライブラリ管理が可能ですが、Ratchetの公式ページに導入方法が記載されています。

http://socketo.me/docs

ComposerでRatchetをインストール

公式ページに書いている通り、composer.jsonを書き換えても良いですし

composer require cboden/ratchet

でも良いです。(執筆時点でのVer.はv0.4.3を使用しています)

WebSocketサーバを作る

Webサーバ内で別のサーバが動くイメージで実装します。

Webサーバ(apache)内でアプリサーバ(tomcat)が動く感覚に近いです。

Java使いはイメージしやすいかも。(厳密には異なる概念です。あくまでイメージね)

require 'vendor/autoload.php';


$app = require 'bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();

$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new Chat()
        )
    ),
    8282
);


$server->run();

ここでは、Laravelのメソッドや環境変数等を使うために「require 'vendor/autoload.php'」したり色々やっています。

これを自作artisanコマンド等で、自動実行できるようにするとこの記述は不要になります。

Laravel上で動くようになるからですね。

コードを見ておや?と思った方がいるかもしれません。

WebSocketはHTTP技術を拡張したものなので、HttpServerクラスでListenを行います。

このHttpServerクラスはRatchetで作られたものですが、RequestオブジェクトはPSR-7 HTTP message interfacesで拾うことができます。

従って、その引数に渡しているWsServerインスタンスやChatインスタンスも同様です。

Chatクラスの中身は、公式ページにも記載がある通りMessageComponentInterfaceを実装する形にします。

これを実装することでWebSocketの各イベントが使用可能になります。

今回、私が実装したのは以下の4つです。

  • onOpen() : クライアントから初めてWebSocketに接続された時に発火するイベント
  • onMessage() : クライアントのsend()時に発火するイベント。クライアントにメッセージを返すところまでここで実装する。
  • onClose() : クライアントから切断(close()時、もしくはブラウザの×ボタン押した時)に発火するイベント
  • onError() : WebSocket通信中に何らかのエラーが発生した時に発火するイベント

まとめ

LaravelでRatchetを扱う時は

  • Composerでライブラリをインストール
  • ListenするWebSocketサーバ(クラス)を作る
  • 各イベントを理解する

をわかっていれば実装できると思います。

まだまだ資料は少なめですが、Ratchet関連の解説記事もそこそこあるので、調べたらいくつか出てきます。

今回はここまでです。良きSocketライフを!(笑)


Wizではエンジニアを募集しております。

興味のある方、ぜひご覧下さい。

careers.012grp.co.jp