4.1. PiaInet 基本機能

PiaInet を利用する場合の手順や注意点を説明します。

初期化関連処理の順序

Pia のモジュールの初期化を 1.4. セットアップの順序 ページの「モジュールの初期化処理/終了処理の順序」の順で行います。
PiaInet を使用する場合は、以下の処理が必要になります。

処理 注意事項
NEX の初期化 PiaInet の初期化よりも前に行います。
インターネットへの接続確立 PiaSession のスタートアップよりも前に行います。
ネットワークサービスの開始 インターネットへの接続確立後から PiaSession のスタートアップまでの間に行います。
NEX ゲームサーバーへのログイン

インターネットへの接続確立後から PiaSession のスタートアップまでの間に行います。

ログインしたゲームサーバー情報の PiaInet への登録 NEX ゲームサーバーへのログイン後から PiaSession のスタートアップまでの間に行います。

終了関連処理の順序

PiaSession のクリーンアップ後、再度 PiaSession のスタートアップからセッション処理を行うことができます。

再スタートアップせずに終了する場合は最初に PiaInet に登録したゲームサーバー情報の設定解除を行います。
次に Pia のモジュールを初期化した順序と逆の順序で終了処理を行います。

NEX ゲームサーバーからのログアウト、ネットワークサービスの停止、インターネット接続の切断処理は PiaSession のクリーンアップ後であれば行えますが、NEX の終了処理は PiaInet の終了処理後よりも後に行う必要があります。

注意:

NEX ゲームーサーバーからログアウトした後、NEX の終了処理を行わず、再度ログインし、PiaSession をスタートアップさせようとすると NEX の不具合によりエラーになってしまいます。ログアウト後は終了処理を行う必要があります。

 

NEX の初期化

PiaInet 内で一部 NEX のクラスを利用しているため、PiaInet の初期化前に NEX の初期化を行う必要があります。具体的には、nn::nex::MemoryManager::SetBasicMemoryFunctions と nn::nex::GlobalVariables::AcquireInstance を呼び出します。

nn::nex::NgsFacade インスタンスもこのタイミングで生成します。インスタンス生成前に PiaInet や PiaSession の初期化を行うと Pia 内部で nn::nex::GlobalVariables::AcquireInstance() が追加で呼び出されてしまいます。その結果、NEX の終了処理で nn::nex::GlobalVariables::ReleaseInstance() を呼び出してもインスタンスが破棄されず NEX のメモリリークが発生してしまうことになります。

PiaInet の初期化

PiaInet モジュールの初期化(inet::Initialize)を行います。

NAT トラバーサル処理などを行う NexFacade クラスのシングルトンを生成します。PiaInet の初期化が完了したら、PiaTransport に nn::pia::inet::NexNetworkFactory を渡して初期化します。PiaTransport の初期化については 6. PiaTransport 編を参照してください。

コード 4-1. PiaInet の初期化
/*
NEX、PiaCommon の初期化を済ませておきます
*/


// PiaInet を初期化します
result = nn::pia::inet::Initialize();
PIA_ASSERT(result.IsSuccess());

// PiaInet で必要なシングルトンの生成を開始します
result = nn::pia::inet::BeginSetup();
PIA_ASSERT(result.IsSuccess());

// NexFacade のシングルトンを生成します
result = nn::pia::inet::NexFacade::CreateInstance();
PIA_ASSERT(result.IsSuccess());

// PiaInet で必要なシングルトンの生成を終了します
result = nn::pia::inet::EndSetup();
PIA_ASSERT(result.IsSuccess());
 
/*
nn::pia::transport::Transport::Setting.pFactory に
nn::pia::inet::NexNetworkFactory のポインタを指定して
PiaTransport の初期化を行います。その後、PiaSession の初期化を行います。
*/

インターネットへの接続

CTR-SDK の AC ライブラリとソケットライブラリを使用してインターネットへの接続を確立します。

ソケットライブラリの初期化時には送受信バッファのサイズ、ソケットを利用するスレッド数、ソケットライブラリに指定するワークメモリのポインタとワークメモリのサイズを指定します。
送受信バッファのサイズは 64KB を指定します。スレッド数は使用する NEX のスレッドモードによって次のようになります。

PiaTransport では 3 つのスレッドからソケットを呼び出します。NEX ではアンセーフトランスポートバッファスレッドモードの場合は 2 つ、アンセーフユーザースレッドモードの場合は 1 つのスレッドからソケットが呼び出されます。

  • NEX がアンセーフトランスポートバッファスレッドモードの場合: 5 スレッド
  • NEX がアンセーフユーザースレッドモードの場合: 4 スレッド

したがって、必要なワークメモリのサイズはスレッド数を threadNum とすると、nn::socket::GetRequiredMemorySize(64*1024, threadNum) で取得できます。
この値を nn::socket::Initialize 関数に指定してソケットライブラリを初期化します。

ネットワークサービスの開始

フレンドサーバーへのログイン

CTR-SDK のフレンドライブラリを使用してフレンドサーバーにログインします。

NEX ゲームサーバーへのログイン

ゲームサーバーへのログインやマッチメイクなどのサーバーサービスには、NEX を通常通り呼び出します。nn:nex::NgsFacade を使用してゲームサーバーにログインします。
ログイン方法については NEX プログラミングマニュアルの「サーバーサービス - 接続処理」を参照してください。

NEX ゲームサーバー情報の設定

ゲームサーバーへのログインに成功したら、nn::pia::inet::NexFacade::LoginInfo のポインタを引数とする Bind() を呼び出してゲームサーバー情報を設定します。引数として渡す inet::NexFacade::LoginInfo は API 呼び出し時のみ参照されます。API 呼び出し後は実体を破棄しても問題ありません。

コード 4-2. NEX ゲームサーバー情報の設定
nn::pia::inet::NexFacade::LoginInfo loginInfo;
loginInfo.gameServerId = MatchmakeGameId; // ゲームサーバーにログインする際に指定したゲームサーバー ID
loginInfo.pNgsFacade = pNgsFacade; // ゲームサーバーにログインした nn::nex::NgsFacade インスタンス
loginInfo.pAccessKey = pAccessKey; // ゲームサーバーにログインする際に指定したアクセスキー
nn::pia::inet::NexFacade::GetInstance()->Bind(&loginInfo);

PiaSession API の呼び出し

ログインに成功したら以降は PiaSession の API を呼び出すことでセッションの構築/参加処理を行います。詳しくは 7.4. 基本機能 - ブラウズマッチメイク7.5. 基本機能 - ランダムマッチメイクを参照してください。

NAT セッションの開始

session::Session のセッション構築/参加を行う非同期処理中に NAT セッション(P2P 通信)が開始されます。また、セッション破棄/離脱を行う非同期処理中に NAT セッションが終了します。

非同期処理を進めるために、1ゲームフレームに1回または2回の頻度で NEX のディスパッチ関数と Pia のディスパッチ関数を呼び出します。また、処理は Pia 内部のバックグラウンドスレッドで実行されるため、バックグラウンドスレッドに処理時間が割り当てられるように、スレッドのスリープを適切に行う必要があります。 

スタートアップ時に NAT 種別判定用サーバーの DNS による名前解決処理を行います。 名前解決処理はバックグラウンドで実行されます。名前解決前にルータの WAN 側のケーブルを抜いたときなどには名前解決処理のタイムアウトを待つため、完了に 30 秒以上かかることがあります。なお、名前解決処理はキャンセルできません。

P2P メッシュネットワークへの参加

P2P メッシュネットワークの参加処理中に、自動的に NAT トラバーサル処理(ステーション間で P2P 通信が行える状態にするための処理)が行われます。全ステーションが EIM であれば NAT トラバーサル処理は短時間で完了します。自分または相手に EDM のステーションが存在する場合、ポート判定処理が必要となるため NAT トラバーサル処理時間が長くなります。ポート判定処理は並列に実行できないため、処理回数に比例して全ステーションとの NAT トラバーサル処理が完了するまでの時間は長くなります。

EDM のポート判定に失敗するなどで NAT トラバーサルに失敗した場合、NAT トラバーサル失敗(ResultNatTraversalFailedLocalEimRemoteEdm など)のエラーとなります。

セッション参加処理の詳細については、プログラミングマニュアル 7.4. 基本機能 - ブラウズマッチメイク7.5. 基本機能 - ランダムマッチメイクを参照してください。

ディスパッチ処理

Pia の ディスパッチ処理

NAT セッション中(セッションスタートアップからクリーンアップまでの間)は、Pia のディスパッチ関数(pia::common::Scheduler)を呼び出します。(Pia のディスパッチについては、6. PiaTransport 編 を参照してください。)

NEX の ディスパッチ処理

NEX 使用中は、サーバーとの通信のために NEX のディスパッチ関数も呼ぶ必要があります。呼び出し順はどちらが先でも問題ありません。PiaInet 使用時は全ての P2P 通信が Pia 側で行われるため、NEX のディスパッチ処理はサーバーとの通信のためだけに行われます。NEX のディスパッチ関数を呼び出す頻度を低くすることで CPU 負荷を下げることができますが、呼び出し間隔が長くなりすぎるとサーバーの動作に支障があるため、100 ミリ秒間隔程度に収まるようにします。

参考:

NEXのディスパッチ処理とPiaのディスパッチ処理は同一スレッドで呼び出す必要があります。

 

コード 4-3. NEX のディスパッチ処理呼び出し頻度の制御
nn::pia::common::Scheduler* pScheduler = nn::pia::common::Scheduler::GetInstance();
if (pScheduler)
{
    result = pScheduler->Dispatch(DispatchTimeout);
}

s_NexDispatchPeriod = NexDispatchPeriodInP2pSession;
if ((nns::pia::sampleframework::SampleFramework::GetInstance()->GetFrameCount() % s_NexDispatchPeriod) == 0)
{
    nn::nex::Scheduler::GetInstance()->Dispatch(NexDispatchTimeout);
}

NEX ゲームサーバー情報の設定解除

NexFacade のクリーンアップ処理後から NEX ゲームサーバーからログアウトするまでの間に NexFacade::Unbind() を呼び出してゲームサーバー情報の設定を解除します。