MRS WebSocket Client

mrs_ws は、 MRSのWebSocket版クライアント mrs.js と、
MRS RoomのWebSocket版クライアント room.js 、
それらを使用するサンプルコード、
テスト用のスクリプトなどを含んでいます。

MRSは Monobit Realtime Server の略で、TCPとUDPに対応した通信ライブラリです。
詳細は、MRSのパッケージに含まれるドキュメントを参照してください。

動作環境

上記2つで検証していますが、Node.jsをインストールできるLinuxで、
またMRSライブラリが動作する環境であれば問題なく動作するはずです。

MRSライブラリ本体とMRS Roomの準備

任意の場所に任意の名前のディレクトリを作成してください。
仮にwork という名前を付けます。

workの直下に、以下のように必要なものが配置されているようにしてください。

MRSライブラリ: work/mrs
MRS Room: work/mrs_room
mrs_ws: work/mrs_ws

MRSライブラリは、ライブラリのサンプルプログラムが格納されている
ディレクトリにアクセスできることが必要です。具体的には次のとおりです。

work/mrs/sample/cpp/mac  (MacOSの場合)
work/mrs/sample/cpp/linux  (Linuxの場合)

MRS Roomについては、配布パッケージに含まれているサンプルプログラムが必要です。具体的には次の通りです。

work/mrs_room/sample/cpp/mac  (MacOSの場合)
work/mrs_room/sample/cpp/linux  (Linuxの場合)

これらのサンプルプログラムを用いて動作確認ができます。

MRSを利用したWebアプリケーションの作り方

2つのパターンでアプリケーションを作ることができます。

まず一つ目の単純なパターンは、mrs.jsのみを使って、
MRSのバイナリレコードを送信してMRSのサーバーと通信して、
アプリケーションを作成する方法です。
このパターンを「MRSアプリケーション」と呼びます。
このパターンのサンプルアプリケーションが cli.html です。
MRSの詳細については、MRSの配布パッケージに含まれる MRS_API_Overview.mdを参照してください。

もうひとつのパターンは、mrs.jsとroom.jsの両方を使って、
MRS Roomのサーバと通信する方法です。
このパターンは「MRS Roomアプリケーション」と呼びます。
ルームサーバーは、サーバー側にゲーム処理を持たないタイプの
マルチプレイゲームを簡単に作るための、ゲームデータの同期用サーバーです。
このパターンのサンプルアプリケーションが、 cli_room.htmlです。
MRS Roomについての詳しい説明は、 MRS Roomの配布パッケージに含まれる ROOM_API_Overview.mdを参照してください。

MRSアプリケーションの実装

MRSアプリケーションの動作するサンプルは cli.html にあります。
ここでは、cli.htmlがどのように実装されているかを解説します。

まず、HTMLで mrs.jsを読み込みます。
HTMLに次のようなタグを追加してください。

<script type="text/javascript" src="mrs.js">  </script>

次に、 createMRSClient 関数を使ってMRSのクライアントを作成します。
この関数は内部でWebSocketを作成し、バイナリモードの通信を設定します。

var cli = createMRSClient("ws://localhost:8888/");

localhost以外でサーバを動作させたい場合は、このURLを直接変更してください。

次にデータを受信したときにアプリケーションが処理を行うために、
コールバック関数を設定します。

cli.onReadRecord = function(payload_type,u8ary,msg) {
  switch(payload_type) {
    case 0x01: // アプリケーションが自由に定義する
    ....
  }
};

payload_typeはMRSのレコードにおけるpayload_typeと同じ意味で、
アプリケーションが処理を分岐するために自由に定義できる値です。
u8aryは Uint8Arrayで渡される生データ、
msgは u8aryをUTF-8の文字列と解釈してstringに変換した値です。

次の例では、文字列をデータとして含むレコードを1個送信しています。
payload_typeは0x01で、文字列の内容が "hello" です。

cli.writeStringRecord( 0x01, "hello" );

次の例では、バイナリデータをUint8Arrayを用いて渡してレコードを1個送信しています。 payload_typeは0x01で、送るデータの内容は 4バイトで、
中身は 0x01,0x02,0x03,0x04 です。

cli.writeRecord( 0x01, new Uint8Array([1,2,3,4]));

HTMLのボタンを押したときになにか送信したい場合は、
以下のようにsend関数を呼ぶように定義し、

<button onclick="send();">send</button>

send関数では次のようにします。

function send() {
  cli.writeStringRecord( 0x01, "hello" );
}

これを試すには、MRSパッケージに含まれるエコーサーバーのプログラムが使えます。

MacOSならば、 mrs/sample/cpp/mac/10.11/echo_serverを、
Amazon LinuxやCentOSならば、 mrs/sample/cpp/linux/centos6_4.4.7/echo_sereverが実行バイナリです。MacOS 10.12や、CentOS7などについてもビルド済みのバイナリが含まれています。

echo_serverをコマンドラインから起動すると次のようになります。

bash$ ./echo_server
sleep_msec=1 server_addr=0.0.0.0 server_port=22222 backlog=10
TCP listening on 0.0.0.0 22222
UDP waiting on 0.0.0.0 22222
WS listening on 0.0.0.0 22223
WSS listening on 0.0.0.0 22224

上からそれぞれ、TCP、UDP、WebSocket、セキュアなWebSocketです。
ポート番号が利用できないなどのエラーの場合は次のように表示されエラー終了します。

TCP mrs_server_create: MRS_EADDRINUSE: Address already in use

cli.htmlをダブルクリックしてブラウザで開くと、次の図のような画面になります。

その際はデバッガコンソールを開くと便利でしょう。

画面の上から、テキスト入力の "Payload_type"で数値を指定すると、送信するレコードのpayload_typeを設定できます。1を指定するとエコーサーバーはエコーしてきますが、1以外だとエコーしません。
"Message"は任意の文字列を指定します。
Repeatは繰り返しの回数を指定します。100を設定すると、同じレコードを100回送信します。
sendボタンをクリックするとレコード送信を実行します。

エコーサーバーが反応を返してきたら、Response:のDOM要素のところに、
次のようなログが表示されます。

payload_type:1 Data:hello_11:0 RTT:4ms

RTTをみると、送信してから受信までに4msの時間がかかったことがわかります。

MRS Roomアプリケーションの実装

MRS Roomアプリケーションの実装も、MRSアプリケーションと基本的には同じで、
クライアントを作成し、コールバック関数を定義し、
送信関数を呼び出すだけです。ただし、
コールバックが2種類になり、送信関数も種類が増えています。

動作するサンプルは cli_room.html です。

ルームやプレイヤーの概念については、MRS Roomのドキュメントを参照してください。

まず、HTMLで mrs.jsとroom.jsを読み込みます。
HTMLに次のようなタグを追加してください。

<script type="text/javascript" src="mrs.js">  </script>
<script type="text/javascript" src="room.js">  </script>

次に、 createMRSClient 関数とcreateMRSRoom関数を使って
MRS Roomのクライアントを作成します。

var cli = createMRSClient("ws://localhost:8888/");
var room = createMRSRoomClient(cli);

以降はここで作成したroomを使ってすべての操作を行います。

データを受信したときにアプリケーションが処理を行うためには、
roomにコールバック関数を設定します。

room.onReadRecord = function(room_id,owner_player_id,member_ids,sender_player_id, payload_type, payload ) {
  // ルームに送信されたレコードを受信した。
}

コールバックの引数に渡される値は次の通りです。

room_id は参加しているルームのID

owner_player_id はルームの所有者のプレイヤーID

member_ids はルームに参加しているプレイヤーIDの配列

sender_player_id は送信したプレイヤーのID

payload_type はアプリケーションが自由に設定するペイロードタイプ

payload は Uint8Arrayの配列で、アプリケーションが送信した生のデータです。

Roomサーバーとの通信においては、 onReadRecordコールバックで受信できる
ゲームデータの同期用のレコードだけではなく、
ルームの参加者が増減したりなどのルームの状態自体に関するイベントもコールバック関数で受信することができます。

そのためには次のように onRoomEvent コールバック関数を登録します。

room.onRoomEvent = function(evt,room_id,player_id,result,members) {
};

コールバック関数の引数は以下の値が渡されます。

evt はイベントの種別で、次のものが定義されています。詳細については、MRS Roomのリファレンスを参照してください。

var MRS_ROOM_EVENT_NONE                    = 0;
var MRS_ROOM_EVENT_CREATE_ROOM             = 1;
var MRS_ROOM_EVENT_CREATE_ROOM_ERROR       = 2;
var MRS_ROOM_EVENT_JOIN_ROOM               = 3;
var MRS_ROOM_EVENT_JOIN_ROOM_ERROR         = 4;
var MRS_ROOM_EVENT_JOIN_ROOM_OTHER_PLAYER  = 5;
var MRS_ROOM_EVENT_LEAVE_ROOM              = 6;
var MRS_ROOM_EVENT_LEAVE_ROOM_OTHER_PLAYER = 7;
var MRS_ROOM_EVENT_SET_OWNER_PLAYER        = 8;

room_idはルームのID

player_idは事象を引き起こしたプレイヤーのID

resultは次の値のいずれかです。

var MRS_ROOM_RESULT_SUCCESS                       = 0;
var MRS_ROOM_RESULT_FAILURE                       = -1;
var MRS_ROOM_RESULT_CANNOT_CREATE_ROOM            = -100;
var MRS_ROOM_RESULT_ROOM_NOT_FOUND        = -101;
var MRS_ROOM_RESULT_PLAYER_ALREADY_JOINED = -102;

membersはルームに参加しているプレイヤーのIDの配列です。

room.sendCreateRoom(room_id,player_id);

作成時のエラーはonRoomEventで通知されます。

room.sendJoinRoom(room_id,player_id);  

参加時のエラーはonRoomEventで通知されます。

room.sendLeaveRoom();
room.sendSetOwner(player_id);
room.broadcastString(payload_type,payload);
room.broadcast(payload_type,payload);

broadcastStringは文字列を、broadcastはUint8Arrayを送信します。

room.othercastString(payload_type,payload);

othercastStringは文字列を、othercastはUint8Arrayを送信します。

room.unicastString(payload_type,payload,player_id);

unicastStringは文字列を、unicastはUint8Arrayを送信します。

room.multicastString(payload_type,payload,[player_id]);  

最後の引数はプレイヤーIDの配列を指定します。
multicastStringは文字列を、multicastはUint8Arrayを送信します。

room.ownercastString(payload_type,payload);  

ownercastStringは文字列を、ownercastはUint8Arrayを送信します。

Roomクライアントの動作確認をするためには、
MRS Roomパッケージに含まれるルームサーバーのサンプルコードが使えます。

Roomサーバーをコマンドラインから起動すると次のようになります。
以下、MacOSでの例ですが、Linuxでもバイナリが用意されています。

bash$ cd mrs_room/sample/cpp/mac/10.11
bash$ ./room_server
sleep_msec=1 server_addr=0.0.0.0 server_port=33333 backlog=10
TCP listening on 0.0.0.0 33333
UDP ready on 0.0.0.0 33333
WebSocket ready on 0.0.0.0 33334

エコーサーバーと異なり、TCP33333番がデフォルトとなっています。
UDPとWebSocketのサーバも同時に起動します。

ブラウザでcli_room.htmlを開きます。

画面の上から、テキスト入力の "Player_id"で数値を指定すると、
これから呼び出すコマンドのplayer_id引数の値として渡されます。
WritePlayerIdを指定すると、broadcastなどのcast系の関数の送信プレイヤーを示すプレイヤーのIDを渡します。
RoomIdに数値を入力すると、room_idの値となり、
PayloadTypeに数値を入れると、 payload_typeとなり、
Payload:に文字列を入れると、ペイロードのデータとしてこの値が使われます。

送信ボタンはいくつもあり、
CreateRoom, JoinRoom, SetOwner, Broadcast, Othercast, Unicast, Multicast, Ownercast をそれぞれ試すことができます。

ページ末尾のResponse: には、受信したイベントとレコードの内容が表示されます。


Copyright © 2019 MONOBIT ENGINE Inc.