MRS APIのセットアップと動作確認

本文書はMRSの開発環境を構築し、動作確認をする方法を説明します。

Cocos2d-xプロジェクトへの組み込み

アーカイブ容量がかなり大きいため、

必要に応じて、

こちらよりダウンロードをお願いいたします。

Cocos2d-x版のドキュメントはアーカイブに同梱しております。

C++プロジェクトへの組み込み

C++プロジェクトでMRSを使うには、ヘッダファイルをインクルードし、ライブラリファイルをリンクします。

組み込みに必要なファイルは以下の位置にあります。

パス 概要
mrs/include C++用のmrsライブラリのヘッダファイルが格納されています
mrs/library/mrs C++用のライブラリファイルがプラットフォームごとに分けて格納されています

ヘッダファイルパスの設定

OSの種類によりません。 mrs/include ディレクトリの位置をコンパイラに設定してください。
以下のコードがコンパイルできたら問題ありません。

#include <mrs.hpp>

Windowsでのリンク(サーバー/クライアント共通)

MRSが提供するライブラリと、それらが依存しているWindowsのライブラリの両方を設定する必要があります。

MRSが提供するライブラリは以下のものがあります。
リンカの入力ファイルに設定してください。

mrs/library/mrs/windows/enet_uv_openssl_1.1.1/{MSVSバージョン}/{MSVSランタイム}/$(Platform)/$(Configuration)/
  mrs.lib
  uv.lib
  enet.lib
  crypto.lib
  ssl.lib

MRSが依存しているライブラリは以下のものがあります。
リンカの入力に設定してください。

Ws2_32.lib
psapi.lib
Iphlpapi.lib
Userenv.lib
winmm.lib
Advapi32.lib
Gdi32.lib
Crypt32.lib

また、コンパイル時に以下のオプションを定義してください。

/EHsc

MacOS Xでのリンク(サーバー/クライアント共通)

以下の位置にあるライブラリファイルをリンク時に指定してください。

mrs/library/mrs/mac/{Macバージョン}/enet_uv_openssl_1.1.1/
  libmrs.a
  libuv.a
  libenet.a
  libcrypto.a
  libssl.a

また、コンパイル時に以下のマクロを定義してください。

-DMRS_MAC

Linuxでのリンク(サーバー/クライアント共通)

以下のライブラリファイルをリンク時に指定してください。

mrs/library/mrs/linux/{OS_GCCバージョン}/enet_uv_openssl_1.1.1/
  libmrs.a
  libuv.a
  libenet.a
  libcrypto.a
  libssl.a

MRSが依存しているライブラリは以下のものがあります。
リンカの入力に設定してください。

pthread
rt
dl

また、以下のマクロをコンパイル時に定義してください。

-DMRS_LINUX

サンプルコードの動作確認

MRSの配布パッケージには、基本的な動作を確認できるソースが含まれています。
ソースはコンパイルすることもできるので、サンプルコードをコピーして開発を始めることも可能です。

サンプルコードは以下の位置にあります。

ソースコードのパス 実行ファイル名 概要
mrs/sample/cpp/source/base_loop.cpp base_loop C++用のmrsライブラリの基本のサンプル
mrs/sample/cpp/source/log.cpp log C++用のmrsライブラリのログ出力のサンプル
mrs/sample/cpp/source/echo_server.cpp echo_server C++用のmrsライブラリのエコーサーバーのサンプル
mrs/sample/cpp/source/echo_client.cpp echo_client C++用のmrsライブラリのエコークライアントのサンプル

サンプルコードの使い方

それぞれのサンプルコードの使い方は、以下の通りです。

ビルド済みの実行ファイルの位置は、OSごとに以下の位置に分けて配置されています。

mrs/sample/cpp/build/
mrs/sample/cpp/build/windows/

MacOS X | Linux | Windowsでサンプルコードをビルドする

セットアップスクリプト(MacOS X | Linux)

スクリプト名 概要
setup_dev.sh 開発環境に必要なパッケージをインストール
setup_ops.sh 運用環境に必要なパッケージをインストール
setup_timezone.sh 指定されたタイムゾーンを設定

上記スクリプトを必要に応じて実行することで、MRSに必要な環境構築を行います。

./setup_dev.sh
./setup_ops.sh
./setup_timezone.sh Asia/Tokyo

MacOS Xでのビルド

cd mrs/sample/cpp/build
MRS_PLATFORM_TYPE=mac MRS_PLATFORM_VERSION=10.12 ./cmake.sh
make clean all

上記を実行すると、mrs/sample/cpp/build以下に、base_loopなど実行ファイルが生成されます。

Linuxでのビルド

cd mrs/sample/cpp/build
MRS_PLATFORM_TYPE=linux MRS_PLATFORM_VERSION=centos7_4.8.5 ./cmake.sh
make clean all

上記を実行すると、mrs/sample/cpp/build以下に、base_loopなど実行ファイルが生成されます。

Windowsでのビルド

cd mrs/sample/cpp/build
MRS_PLATFORM_TYPE=windows MRS_PLATFORM_VERSION=2017 ./cmake.sh

上記を実行すると、mrs/sample/cpp/build/windows以下に、2017_MT_x64_Release/mrs_sample.slnなどのファイルが生成されます。

エコーサンプルの詳細

echo_serverと echo_clientは、ゲームサーバー開発の起点となるプログラムです。
ここでは動作確認の方法を詳しく説明します。

echo_server

コマンドライン引数の意味は次の通りです。

./echo_server <スリープ時間(ミリ秒)> <サーバーのアドレス> <サーバーのポート番号> <バックログ数> <レコードによる送受信を行うかどうか>

標準出力の例

$ ./echo_server 
arg 01: sleep_msec [1]
arg 02: server_addr [0.0.0.0]
arg 03: server_port [22222]
arg 04: backlog [10]
arg 05: is_valid_record(OFF:0 ON:1) [1]
sleep_msec=1 server_addr=0.0.0.0 server_port=22222 backlog=10 arg_is_valid_record=1
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_SSL listening on 0.0.0.0 22225
MRU waiting on 0.0.0.0 22226

echo_client

コマンドライン引数の意味は次の通りです。

./echo_client <コネクションタイプ> <鍵交換フラグ> <レコード暗号フラグ> <送信データ長> <送信レコード数> <送信コネクション数> <スリープ時間(ミリ秒)> <サーバーのアドレス> <サーバーのポート番号> <タイムアウト時間(ミリ秒)> <レコードによる送受信を行うかどうか> <WS|WSS接続時に指定するパス>

echo_clientは、echo_serverを起動した後に起動してください。

echo_clientによる通信遅延時間の計測

1. TCP + 暗号化無レコードの送信

通信を始めると、以下のフォーマットでログが出力されます。

read_echo data=TCP NOCRYPT <コネクション番号>: <レコード番号> data_len=1024 diff_time=<遅延時間(秒.マイクロ秒)>(<受信時間> - <送信時間>)

標準出力の例

$ ./echo_client 1 1 0
arg 01: connection_type(TCP:1 UDP:2 WS:3 WSS:4 TCP_SSL:5 MRU:6 TCP -> WSS -> WS:*) [1]
arg 02: is_key_exchange(OFF:0 ON:1) [1]
arg 03: is_encrypt_records(OFF:0 ON:1) [1]
arg 04: write_data_len [1024]
arg 05: write_count [10]
arg 06: connections [1]
arg 07: sleep_msec [1]
arg 08: server_addr [127.0.0.1]
arg 09: server_port [22222]
arg 10: timeout_msec [5000]
arg 11: is_valid_record(OFF:0 ON:1) [1]
arg 12: connection_path [/]
connection_type=1 is_key_exchange=1 is_encrypt_records=0 write_data_len=1024 write_count=10 connections=1 sleep_msec=1 server_addr=127.0.0.1 server_port=22222 timeout_msec=5000 is_valid_record=1 connection_path=/
on_fallback_connect connection_type=1 addr=127.0.0.1 port=22222 timeout_msec=5000
on_connect local_mrs_version=0x2000000 remote_mrs_version=0x2000000
on_key_exchange
parse_record seqnum=3 options=0x00 payload=0x01/1036
read_echo data=TCP NOCRYPT 1: 1 data_len=1024 diff_time=0.000122(1567480792.207487 - 1567480792.207365)
parse_record seqnum=4 options=0x00 payload=0x01/1036
read_echo data=TCP NOCRYPT 1: 2 data_len=1024 diff_time=0.001563(1567480792.208944 - 1567480792.207381)
parse_record seqnum=5 options=0x00 payload=0x01/1036
read_echo data=TCP NOCRYPT 1: 3 data_len=1024 diff_time=0.001571(1567480792.208959 - 1567480792.207388)
parse_record seqnum=6 options=0x00 payload=0x01/1036
read_echo data=TCP NOCRYPT 1: 4 data_len=1024 diff_time=0.001575(1567480792.208969 - 1567480792.207394)
parse_record seqnum=7 options=0x00 payload=0x01/1036
read_echo data=TCP NOCRYPT 1: 5 data_len=1024 diff_time=0.001578(1567480792.208978 - 1567480792.207400)
parse_record seqnum=8 options=0x00 payload=0x01/1036
read_echo data=TCP NOCRYPT 1: 6 data_len=1024 diff_time=0.001573(1567480792.208984 - 1567480792.207411)
parse_record seqnum=9 options=0x00 payload=0x01/1036
read_echo data=TCP NOCRYPT 1: 7 data_len=1024 diff_time=0.001569(1567480792.208990 - 1567480792.207421)
parse_record seqnum=10 options=0x00 payload=0x01/1036
read_echo data=TCP NOCRYPT 1: 8 data_len=1024 diff_time=0.001569(1567480792.208996 - 1567480792.207427)
parse_record seqnum=11 options=0x00 payload=0x01/1036
read_echo data=TCP NOCRYPT 1: 9 data_len=1024 diff_time=0.001570(1567480792.209002 - 1567480792.207432)
parse_record seqnum=12 options=0x00 payload=0x01/1036
read_echo data=TCP NOCRYPT 1: 10 data_len=1024 diff_time=0.001569(1567480792.209009 - 1567480792.207440)
Since all records have been received, it is finished.
on_disconnect local_mrs_version=0x2000000 remote_mrs_version=0x2000000

2. TCP + 暗号化有レコードの送信

通信が始まると、以下のフォーマットでログが出力されます。

read_echo data=TCP   CRYPT <コネクション番号>: <レコード番号> data_len=1024 diff_time=<遅延時間(秒.マイクロ秒)>(<受信時間> - <送信時間>)

標準出力の例

$ ./echo_client 1 1 1
arg 01: connection_type(TCP:1 UDP:2 WS:3 WSS:4 TCP_SSL:5 MRU:6 TCP -> WSS -> WS:*) [1]
arg 02: is_key_exchange(OFF:0 ON:1) [1]
arg 03: is_encrypt_records(OFF:0 ON:1) [1]
arg 04: write_data_len [1024]
arg 05: write_count [10]
arg 06: connections [1]
arg 07: sleep_msec [1]
arg 08: server_addr [127.0.0.1]
arg 09: server_port [22222]
arg 10: timeout_msec [5000]
arg 11: is_valid_record(OFF:0 ON:1) [1]
arg 12: connection_path [/]
connection_type=1 is_key_exchange=1 is_encrypt_records=1 write_data_len=1024 write_count=10 connections=1 sleep_msec=1 server_addr=127.0.0.1 server_port=22222 timeout_msec=5000 is_valid_record=1 connection_path=/
on_fallback_connect connection_type=1 addr=127.0.0.1 port=22222 timeout_msec=5000
on_connect local_mrs_version=0x2000000 remote_mrs_version=0x2000000
on_key_exchange
parse_record seqnum=3 options=0x01 payload=0x01/1036
read_echo data=TCP   CRYPT 1: 1 data_len=1024 diff_time=0.000461(1567480796.171236 - 1567480796.170775)
parse_record seqnum=4 options=0x01 payload=0x01/1036
read_echo data=TCP   CRYPT 1: 2 data_len=1024 diff_time=0.000449(1567480796.171266 - 1567480796.170817)
parse_record seqnum=5 options=0x01 payload=0x01/1036
read_echo data=TCP   CRYPT 1: 3 data_len=1024 diff_time=0.000461(1567480796.171309 - 1567480796.170848)
parse_record seqnum=6 options=0x01 payload=0x01/1036
read_echo data=TCP   CRYPT 1: 4 data_len=1024 diff_time=0.000433(1567480796.171329 - 1567480796.170896)
parse_record seqnum=7 options=0x01 payload=0x01/1036
read_echo data=TCP   CRYPT 1: 5 data_len=1024 diff_time=0.000383(1567480796.171345 - 1567480796.170962)
parse_record seqnum=8 options=0x01 payload=0x01/1036
read_echo data=TCP   CRYPT 1: 6 data_len=1024 diff_time=0.003025(1567480796.174018 - 1567480796.170993)
parse_record seqnum=9 options=0x01 payload=0x01/1036
read_echo data=TCP   CRYPT 1: 7 data_len=1024 diff_time=0.002997(1567480796.174040 - 1567480796.171043)
parse_record seqnum=10 options=0x01 payload=0x01/1036
read_echo data=TCP   CRYPT 1: 8 data_len=1024 diff_time=0.002986(1567480796.174058 - 1567480796.171072)
parse_record seqnum=11 options=0x01 payload=0x01/1036
read_echo data=TCP   CRYPT 1: 9 data_len=1024 diff_time=0.002949(1567480796.174075 - 1567480796.171126)
parse_record seqnum=12 options=0x01 payload=0x01/1036
read_echo data=TCP   CRYPT 1: 10 data_len=1024 diff_time=0.002929(1567480796.174092 - 1567480796.171163)
Since all records have been received, it is finished.
on_disconnect local_mrs_version=0x2000000 remote_mrs_version=0x2000000

psコマンドによるメモリやCPU使用量の計測

各サンプルプログラムがどの程度の量のメモリやCPUを使用しているかは、ps コマンドで知ることが可能です。

以下を参考にしてください。

http://qiita.com/white_aspara25/items/cfc835006ae356189df3

実際の例

$ ps aux | grep echo
   3017  4.4  0.6  21092  3220 pts/0    S+   21:00   0:01 ./echo_server
   3019  4.2  0.4  20036  2196 pts/1    S+   21:01   0:01 ./echo_client

C#プロジェクトへの組み込み

C#プロジェクトにMRSを使うには、まずC#フレームワークを選択します。

フレームワーク 概要
.NET Core 2.0以降 マルチプラットフォームのC#フレームワーク。推奨フレームワークです。サンプルプログラムではこちらを使用しています。
.NET Framework Windows専用のフレームワークです。Windowsでのみ使用するならこちらを選択します。

ここでは推奨フレームワークである.NET Coreのバージョン2.1系を用いて説明していきます。

.NET Coreのインストール

以下のサイトから各プラットフォームに.NET Core SDKをダウンロードして、インストールしてください。

https://github.com/dotnet/core/blob/master/release-notes/2.1/2.1.12/2.1.12-download.md

CentOS上でのインストール方法については、以下のシェルを実行してください。

mrs\sample\csharp\netcoreapp2.1\script\inst.h

$ sh inst.sh

最新版の.NET Coreを使用する場合などは、以下を参考にしてください。

上記のシェル内に記述されている.NET Coreのバージョンを変更すればインストールが可能です。

https://github.com/dotnet/core/blob/master/release-notes/2.2/2.2.6/2.2.6-download.md

.NET Coreでのプロジェクト作成

.NET Core 2.0以降においては、VisualStudio 2017以降を使用してプロジェクトを作成します。

「ファイル」→「新規作成」→「プロジェクト」でプロジェクト作成ダイアログを開き、

「Visual C#」→「.NET Core」→「コンソール アプリ(.NET Core)」を選択してプロジェクト作成を作成します。

空プロジェクトを作成すると、プロジェクトファイル内は以下のような内容で作成されます。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>

</Project>

プロジェクト作成上のワンポイント

プロジェクトのビルドイベントで、ファイルコピーなどを行う事があります。(mrs.dllなど)

Linux上でシェルを実行した際に、コピーのエラーの元となりますので、LinuxとWindowsではプロジェクトを分けておくと便利です。

.NET Coreでのビルド&実行

.NET Coreを使用してのビルド&実行の手順です。

尚コマンドは、Windowsのバッチ処理や、Linux上のシェルからも同じ構文となります。

.NET Coreを使用してのビルドコマンドは以下の通りになります。

dotnet restore {プロジェクト名}.csproj
dotnet publish {プロジェクト名}.csproj --configuration {Debug|Release}

dotnetコマンドではpublishを指定してビルドしています。これはpublishを指定すると、特定フォルダに実行に必要なファイル一式がコピーされ、ビルド後にフォルダを移動しても実行できるからです。

.NET Coreを使用しての実行コマンドは以下の通りになります。

出力フォルダがデフォルトでDebugビルドの場合
dotnet bin/Debug/netcoreapp2.1/publish/{プロジェクト名}.dll

プロジェクトを選択しても実行できます
dotnet run {プロジェクト名}.csproj --configuration {Debug|Release}

C#用MRSクラスライブラリをプロジェクトに組み込む

ここまでで.NET Core2.1のプロジェクトを作成しましたので、次はMRSクラスライブラリを組み込んでいきます。

パス 概要
mrs\sample\csharp\libmrs\Monobit\mrs MRS用のクラスライブラリが入っています。
mrs\sample\csharp\netcoreapp2.1\2017 各フォルダにはC#用のサンプルアプリのプロジェクトファイルやビルド&実行スクリプトが入っています。
mrs\sample\csharp\source C#用のサンプルアプリのソースコードが入っています。

MRSクラスライブラリを参照するために、プロジェクトに参照パスを追加します。

MRSクラスライブラリでは高速化のためにunsafeコードを使っていますので、

PropertyGroupの中でunsafeコードの許可も同時にプロジェクトに追加しておきます。

最後にビルド後のイベントとして、PostBuildEventにてmrs.dllをパッケージよりコピーしてきます。

mrs.dllはVisualStudio 2015でビルドされたもので問題ありません。

但し、このコピーコマンドを入れるとLinux上では当然のようにエラーが表示されます。

そのためPostBuildEventを省いたLinux版のプロジェクトファイルを作っておくと便利です。

下記の例では、サンプルアプリのフォルダ位置と同列の場所にWindows版のプロジェクトファイルを作成している例となります。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="..\..\source\base_loop.cs" />
    <Compile Include="..\..\libmrs\Monobit\mrs\Mrs.cs" />
    <Compile Include="..\..\libmrs\Monobit\mrs\MrsBuffer.cs" />
    <Compile Include="..\..\libmrs\Monobit\mrs\MrsDateTime.cs" />
    <Compile Include="..\..\libmrs\Monobit\mrs\MrsTime.cs" />
    <Compile Include="..\..\libmrs\Monobit\mrs\MrsUtility.cs" />
  </ItemGroup>

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="copy $(ProjectDir)..\..\..\..\..\library\mrs\windows\enet_uv_openssl_1.1.1\2017\MT\x64\$(ConfigurationName) $(OutDir)&#xD;&#xA;" />
  </Target>

</Project>

C#版サンプルコードの動作確認

C++版同様にサンプルコードをコピーして開発を始めることが可能です。

サンプルコードは以下の位置にあります。

パス 概要
mrs\sample\csharp\source\base_loop.cs C#用のmrsライブラリの基本のサンプル
mrs\sample\csharp\source\base_server.cs C#用のmrsライブラリ+プラットフォーム共通シグナル基本処理
mrs\sample\csharp\source\base_server_linux.cs C#用のmrsライブラリ+Linux用シグナル基本処理
mrs\sample\csharp\source\base_server_win.cs C#用のmrsライブラリ+Windows用シグナル基本処理
mrs\sample\csharp\source\echo_client.cs C#用のmrsライブラリのエコーサーバーのサンプル
mrs\sample\csharp\source\echo_server.cs C#用のmrsライブラリのエコークライアントのサンプル
mrs\sample\csharp\source\log.cs C#用のmrsライブラリのログ出力のサンプル

C#版サンプルコードの使い方

基本的にC++版サンプルコードの使い方に準じます。

但し、実行コマンドが異なるので注意が必要です。

上記に実行コマンドを説明していますので、参照してください。

実行コマンド以外では、引数の指定方法が違います。
例としてecho_serverの引数の指定方法を説明します。

dotnet bin/Debug/netcoreapp2.1/publish/echo_server.dll --sleep_msec=1 --server_addr="0.0.0.0" --server_port=22222 --backlog=10

C#版の注意点

.NET Coreでは、C++と違いOSからのシグナル処理の対応がプラットフォーム間においてまちまちです。

その為、MRSにおいてはプラットフォーム間のシグナル処理を吸収した便利クラスがありますので、

実装のお役に立ててください。

・ExitSignalの使い方
using()内で使用します。
以下のようにSetSignal()で設定したハンドラ内でループフラグをOFFにして、
正常にループを終了させる事ができます。

using System.Threading;
using MrsLibs.Signal

class Hoge
{
    private static volatile bool s_bIsRun = true;

    publib static void Main(string[] args)
    {
        using(var sig = new ExitSignal())
        {
            sig.SetSignal((obj, e) => {
                var ev_arg = e as SignalEventArgs;
                Console.WriteLine($"Event: {event_args.SignalEnums}");
                s_bIsRun = false;
                Thread.Sleep(10);
            });

            while(s_bIsRun)
            {
                // ループ処理
                ...
            }
        }
    }
}


ちなみに名前空間のMrsLibsは、
mrs/sample/csharp/source/base_libs.cs
に定義されています。

Copyright © 2019 MONOBIT ENGINE Inc.