0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Websocketサーバーの開発環境を作ってみました

Last updated at Posted at 2024-06-01

はじめに

この記事でご紹介している環境はデモ版としてご紹介させて頂いたWebsocketサーバーからコマンド部を含めWebsocketに不要な部分を取り除いて再構築したものです。

プロトコルの主要な部分は実装済みなので、コマンド部を自分で作成しながらブラウザを使って動作確認できますので、新規でプロジェクトを起こす場合に比べてソケット通信初心者向けの環境と言えます。

デモ版の環境については以下のページでご紹介しています。

以降ではインストール方法と実装例を見ながら進めていきます。

環境

プラットフォーム
Windows10
統合環境
Xampp v3.3.0
ブラウザ
Chrome v123.0.6312.123
言語
PHP v8.2.4(v8.1.0以降)

ここではXAMPP環境を使っている前提で説明していますが、デフォルトとは別の場所に格納している場合やLinux等の別の環境で利用されている場合は適宜読み替えてください。

インストール

以下のコマンドでインストールできます。

Websocket開発環境のインストール
> composer create-project socket-manager/websocket-project <インストール先のディレクトリ名>

GitHubから直接ダウンロードされる場合は以下のページからどうぞ。


それでは上記でインストールしたプロジェクトルートに移動して`php worker`コマンドを実行してみます。
Usage表示
> php worker

SOCKET-MANAGER Framework 1.0.0
Usage:
  command [arguments]

 main
  app:websocket-server                           Websocketサーバー
 craft
  craft:init <初期化クラス名>                     初期化クラスの生成
  craft:parameter <UNITパラメータクラス名>        UNITパラメータクラスの生成
  craft:protocol <プロトコルUNIT定義のクラス名>   プロトコルUNIT定義のクラスとステータス名Enumの生成
  craft:command <コマンドUNIT定義のクラス名>      コマンドUNIT定義のクラスとキュー/ステータス名Enumの生成
  craft:main <メイン処理のクラス名>               メイン処理クラスの生成
  craft:setting <設定ファイル名>                  設定ファイルの生成
  craft:locale <メッセージファイル名>             メッセージファイルの生成

ご覧のようにapp:websocket-serverが含まれている事が確認できます。
これを以下のように実行する事でサーバーを起動できます。

Websocketサーバーの起動
> php worker app:websocket-server [<ポート番号>]

コマンドの詳しい使い方は以下のページでご紹介しています。

実装例

ここではコマンド処理部分のチャットメッセージを実装してみます。

クライアントの実装

このプロジェクトではclientディレクトリに検証用として最低限の実装でファイルを同梱しています。
それではclientディレクトリ内のtest.jsを編集します。
test.js内には以下のようにonopenメソッドがあるのでここに処理を入れます。

onopenメソッドの実装:app/client/test.js
// Websocket接続
websocket = new WebSocket(uri);

/**
 * 接続完了イベント
 * 
 * @param {*} event イベントインスタンス
 * @returns 
 */
websocket.onopen = function(event)
{
    let data =
    {
          'cmd': 'message'
        , 'comment': 'テスト'
    };
    websocket.send(JSON.stringify(data));
};

onopenメソッドはWebsocketの接続が確立した時に呼び出されるイベントです。
上記のようにコマンド名はmessage、送信コメントはテストにしてJSONデータを送信する処理を入れています。

そして以下のようにonmessageメソッドで受信したデータを受け取れますので受信したデータはコンソールに表示されるようになっています。

onmessageメソッド:app/client/test.js
/**
 * データ受信イベント
 * 
 * @param {*} event イベントインスタンス
 * @returns 
 */
websocket.onmessage = function(event)
{
    let data = JSON.parse(event.data);

    console.dir(data);
};

サーバーの実装

まずはCommandForWebsocketQueueEnum.phpのファイルに今回追加するコマンド名を定義します。

キュー名の追加:app/CommandUnits/CommandForWebsocketQueueEnum.php
<?php
/**
 * コマンド部のキュー名のENUMファイル
 * 
 * Websocket用
 */

namespace App\CommandUnits;


/**
 * コマンド部のキュー名定義
 * 
 * Websocket用
 */
enum CommandForWebsocketQueueEnum: string
{
    case MESSAGE = 'message';
}

次にCommandForWebsocket.phpを編集します。

ステータスUNITの実装:app/CommandUnits/CommandForWebsocket.php
class CommandForWebsocket implements IEntryUnits
{
    /**
     * @var const QUEUE_LIST キュー名のリスト
     */
    protected const QUEUE_LIST = [
        CommandForWebsocketQueueEnum::MESSAGE->value,
    ];

    /**
     * キューリストの取得
     * 
     * @return array キュー名のリスト
     */
    public function getQueueList(): array
    {
        return (array)static::QUEUE_LIST;
    }

    /**
     * ステータスUNITリストの取得
     * 
     * @param string $p_que キュー名
     * @return array キュー名に対応するUNITリスト
     */
    public function getUnitList(string $p_que): array
    {
        $ret = [];

        if($p_que === CommandForWebsocketQueueEnum::MESSAGE->value)
        {
            $ret[] = [
                'status' => CommandForWebsocketStatusEnum::START->value,
                'unit' => $this->getMessageStart()
            ];
        }

        return $ret;
    }

    protected function getMessageStart()
    {
        return function(ParameterForWebsocket $p_param): ?string
        {
            $p_param->logWriter('debug', ['COMMAND:MESSAGE' => 'START']);

            $w_ret = $p_param->getRecvData();
            $msg = $w_ret['data'];

            $data =
            [
                'data' => $msg
            ];
            $p_param->setSendStackAll($data);

            return null;
        };
    }
}

追加したポイントは以下の通り。

■QUEUE_LISTへEnum値を追加
MESSAGEというキュー名を追加
■getUnitListメソッドの実装
MESSAGEコマンドに対応するUNIT(メソッド)処理を登録
■getMessageStartメソッドの実装(※)
受信したデータを配信する処理を実装(上記ソース内のlogWriterメソッドでログ出力できます)

引数のParameterForWebsocketクラスはSocketManagerParameterクラスを継承しています。詳しくはSocketManagerParameterクラスの>>Referenceをご覧ください。

動作確認

以下のコマンドを実行してサーバーを10000ポートで起動します。

Websocketサーバーの起動
> php worker app:websocket-server 10000

次にクライアントをブラウザで開きます。
client/test.htmlをブラウザへドラッグ&ドロップした上でF12を押して以下の画面を開いてください。

browser.png

この状態で接続ボタンをクリックすると以下のようにコンソール画面でメッセージコマンドが返ってきている事が確認できます。

browser_exec.png

そしてさらにブラウザをもう一つ開いて同じ操作をすると二つのブラウザウインドウに同じメッセージが配信されている事が確認できますので色々と試してみてください。

ログ出力について

以下のディレクトリ構成でログファイルが出力されます。

ログ出力先のディレクトリ
/logs
    /socket-manager-log     Websocketサーバーのログ

ファイルの命名規則は次の通り。

■Websocketサーバーのログ
<日付文字列("Ymd"形式)>_W<ポート番号>.log

おわりに

コマンド処理は上記で実装したように以下の流れが基本となります。

1.受信データの取得
getRecvDataメソッドで取得
2.送信データの作成
シリアライズ前のデータを作成する
3.送信データの設定
setSendStack、setSendStackAllメソッドで設定

Websocket開発環境では上記のようにコマンド部の処理を追加していく事でサーバーコンテンツを作成していく事になります。

以下のページであらかじめアーキテクチャの内容を理解して頂いた方がより高度な実装が可能になりますので興味のある方はご覧ください。

ホスト名やポート番号等の設定ファイルの詳細は以下のページでまとめています。

自作のプロトコルを実装する必要がある場合は以下の記事をご覧ください。

ここでご紹介したプロジェクトはLaravelと連携できます。
ご興味のある方は以下の記事をご覧ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?