# room\_broadcast

## room\_broadcast サンプル

### 概要

room\_broadcast サンプルは Diarkis サーバーの Room と P2P 機能を使用したサンプル・プログラムです。2人のユーザーが同じ Room に接続し、Room 経由のリレー通信を行った後、P2P 接続を行い P2P でも通信を行う内容となっています。\
room\_broadcast サンプルでは以下の機能を確認することができます。

* Room の作成
* Room への参加
* Room メンバーへのメッセージ送信
* P2P の開始
* P2P でのメッセージの送受信

### ローカル環境でサーバーを起動する

サンプルで使用するサーバーを起動するためのチュートリアルを実施して、ローカル環境で Diarkis サーバーを起動します。

[1. Diarkis サーバーをローカル環境で起動する](/getting-started/tutorial/setup-local-server.md)

### サンプルの引数

サンプルの起動時には以下の３つのパラメータを指定してください。

| 引数         | 説明                            |
| ---------- | ----------------------------- |
| serverAddr | Diarkis サーバのエンドポイントを指定してください  |
| UID        | 接続するユーザーの ID を任意の文字列で指定してください |
| clientKey  | クライアントキーを任意の文字列で指定してください      |

#### 起動例：

`room_broadcast.exe 192.168.1.123:7000 1111 AAAA`

## room\_broadcast サンプル解説

1. Diarkis ランタイムおよび Diarkis Module を初期化し、Diarkis サーバーへ接続します。\
   詳細については [Diarkis モジュール利用の全体的な流れ](https://help.diarkis.io/diarkis-client/samples/cpp/pages/r3yF3oFZnxAPw2prL13v#diarkis-モジュール利用の全体的な流れ) を参照してください。
2. 各機能の初期化処理を行います。 本サンプルでは Room モジュールと P2P モジュールを使用するため、Diarkis Module でそれらの機能を初期化します。

   ```
   // diarkis =  Diarkis::DiarkisAllocShared<DiarkisInterface>(uid); 
   ...
   // P2P モジュールのセットアップ
   diarkis->SetupP2P();

   // Room モジュールのセットアップ
   diarkis->SetupRoom(false);

   ```
3. Room の RandomJoin で Room に入室します。 `DiarkisRoomBase::RandomJoinRoom()` は参加可能な Room がすでに存在すればその Room に参加し、存在しなければ新たに Room を作成します。また、`DiarkisRoomBase::RandomJoinRoom()` でサーバーへリクエストを送信後、実際に Room に参加が完了するまで `DiarkisRoomBase::IsJoin()` を使用して状態をチェックします。

   ```cpp
   diarkis->RandomJoinRoom(10, 60, 0, true);

   // DiarkisRoomBase::OnRoomJoinを待つ
   while (diarkis->GetRoomBase()->IsJoin() == false) {
       std::this_thread::sleep_for(std::chrono::milliseconds(30));
   }
   ```
4. Room に想定されている人数が参加するまで待機します。\
   本サンプルでは 2 ユーザーが同じ Room に参加するまで待機しています。 `DiarkisRoomBase::SendGetMemberIDs()` を呼び出すと Room に参加しているメンバーのリストの取得をサーバーにリクエストすることが可能です。結果は `DiarkisRoomBase::GetRoomMembers()` で取得することができます。

   ```cpp
   while (1)
   {
       Diarkis::StdVector<Diarkis::StdString> members;

       diarkis->GetRoomBase()->SendGetMemberIDs();
       diarkis->GetRoomBase()->GetRoomMembers(members);

       if (members.size() == NumPeer)
       {
           break;
       }
       std::this_thread::sleep_for(std::chrono::milliseconds(2000));
   }
   ```
5. Room の Broadcast で Room に参加しているユーザー全員にメッセージを送信します。

   ```cpp
   diarkis->GetRoomBase()->SendBroadcastToRoom(buff, bReliable);
   ```
6. Room のオーナーは `DiarkisRoomBase::SendStartP2PSync()` を実行してサーバーへ P2P 接続の開始を通知し、Room に参加しているメンバーの接続先のアドレス・リストを取得します。

   ```cpp
   if (Diarkis::StdString(uid.c_str()) == diarkis->GetRoomBase()->GetOwnerUID())
   {
       // 各メンバーの接続先のアドレスリストを取得する
       diarkis->GetRoomBase()->SendStartP2PSync();
   }

   ```
7. Room のオーナーが `DiarkisRoomBase::SendStartP2PSync()` を実行すると Room に参加しているユーザー全員に `DiarkisRoomBase::OnStartP2PSync()` で P2P 接続情報が通知され、これをトリガーにホールパンチを開始します。
8. ホールパンチに成功したら、P2P で通信します。

   ```cpp
   diarkis->GetP2PBase()->SendBroadcast(buff, RudpType::UNRELIABLE_UNORDERED);
   ```
9. `DiarkisRoomBase::SendLeaveRoom()` を実行して Room から退室をサーバーへリクエストします。 本サンプルでは `DiarkisRoomBase::IsLeave()` を使用して Room から Leave が完了するまで待機しています。

   ```cpp
   // Roomから退出
   diarkis->SendLeaveRoom();

   // DiarkisRoomBase::OnRoomLeaveを待つ
   while (diarkis->GetRoomBase()->IsLeave() == false) {
       std::this_thread::sleep_for(std::chrono::milliseconds(30));
   }
   ```
10. 終了処理\
    詳細については [Diarkis モジュール利用の全体的な流れ](https://help.diarkis.io/diarkis-client/samples/cpp/pages/r3yF3oFZnxAPw2prL13v#diarkis-モジュール利用の全体的な流れ) を参照してください。

## 注意点

* P2P のホールパンチを成功させるためには、P2P するクライアントが同じ Room に入っている状態でアドレスを交換して実施しています。
* 複数のクライアントをご用意頂き、同時に実行して動作を確認してください。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://help.diarkis.io/diarkis-client/samples/cpp/room-broadcast.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
