> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Using direct peer-to-peer connections

> PlayFab Party でダイレクト ピア接続を有効にして、透過的なクラウド リレーではなく、エンドポイント間で直接トラフィックをルーティングすることでレイテンシを削減します。

# PlayFab Party とダイレクト ピアツーピア接続

このページでは、サンプルのゲーム コードを使用して PlayFab Party でダイレクト ピアツーピア接続を有効にして使用する方法を説明します。ゲームでダイレクト ピアツーピア接続をいつ使用するかを評価するのに役立つ考慮事項も含まれています。

## ダイレクト ピアツーピア接続を使用するタイミング

PlayFab Party は多種多様な通信トポロジをサポートします。概念的には、すべてのチャットまたはデータ メッセージは、あるピア デバイスまたはユーザーから他のデバイスまたはユーザーへ直接送信されます。しかし、Party はダイレクト ピアツーピア接続の確立に伴う一般的な環境やセキュリティの問題を回避するために、透過的なクラウド リレー サービスを自動的に活用します。バックグラウンドのサービス品質 (QoS) 測定を活用することで、低レイテンシのデータ転送を実現できます。(詳細については、[PlayFab Party の QoS 測定](/services/playfab/multiplayer/networking/concepts-regions) を参照してください。) データ転送のレイテンシをさらに削減するために、必要に応じてダイレクト ピアツーピア接続を有効にできます。以下の「セキュリティに関する考慮事項」で詳述するセキュリティ上の懸念により、Microsoft は、タイトルに厳しいレイテンシ要件がない限り、ダイレクト ピアツーピア接続を有効にする代わりに、当社のクラウド リレー サービスを使用することを推奨します。

### プラットフォームのサポート

ダイレクト ピア接続は、Party ライブラリの Windows 10、Microsoft Game Core、Nintendo Switch、PlayStation®4、および PlayStation®5 バージョンでサポートされています。ライブラリの他のバージョンは、クライアント API を通じて指定されたダイレクト ピア接続オプションに関係なく、常にクラウド リレーを使用してデータを転送します。

「PlayStation」は Sony Interactive Entertainment Inc. の登録商標または商標です。

### セキュリティに関する考慮事項

ダイレクト ピア接続はクライアント間で直接データを送信するために使用されるため、クライアントは全員が互いにどのように接続するかを知る必要があります。これは、同じゲーム セッション内でクライアント間でクライアント IP アドレスを共有することで行われます。たとえば、16 プレイヤーのマルチプレイヤー ゲームがダイレクト ピア接続を使用してプレイヤーの位置を更新する場合、16 のゲーム クライアントのそれぞれが、データを送信する対象を知るために他の 15 のクライアントの IP アドレスを知る必要があります。

ゲーム クライアント間で IP アドレスを共有することはセキュリティ リスクです。IP アドレスを共有することは、悪意のある行為者がその IP アドレスを検出し、ゲームの外部で他のプレイヤーを悪意を持って攻撃するために使用することを許してしまう可能性があります。これらの攻撃を実行する一般的な方法は、DoS (サービス拒否) 攻撃、またはその亜種である DDoS (分散型サービス拒否) 攻撃を通じてです。攻撃は、余分なネットワーク トラフィックでネットワークを圧倒しようとすることで機能します。攻撃者が被害者に十分なネットワーク トラフィックを送信できる場合、被害者のネットワーク ハードウェア (モデムとルーター) は余分なトラフィックの処理にすべての時間を費やす必要があり、正当なネットワーキング接続を処理するという通常の仕事を行う時間がなくなります。実質的に、これは被害者が攻撃の全期間にわたってネットワークを使用できなくなることを意味します。これはしばしば「オフラインにされる」と呼ばれます。

まとめると、成功したダイレクト ピア接続は、一部のデバイス間で低レイテンシを提供する可能性があります。しかし、それを確立しようとすることは、ユーザーが自身の IP アドレスを他者に開示することを必要とし、悪意のあるユーザーがタイトル外でそれらのデバイスやインターネット接続を攻撃できるようになる可能性があります。ダイレクト ピア接続は、ポリシー上の理由で特定のプラットフォームで許可されない場合もあります。パフォーマンスとセキュリティの目標に適したダイレクト ピア接続オプションを使用するようにしてください。リスクを検討した上でダイレクト ピア接続を使用することを決めた場合、以下の例を使用してネットワーク単位およびデバイス単位でタイトルをオプトインしてください。

### LAN シナリオ

Party のダイレクト ピア接続は、LAN シナリオで非常に低いレイテンシを可能にするために使用できます。ただし、これらのシナリオでも、ユーザー認証、LiveOps のデータとインサイト、およびボイス チャット アクセシビリティ機能をサポートするためには、限定的なインターネット接続が必要です。

### アップストリーム帯域幅に関する考慮事項

ダイレクト ピアツーピア接続の使用は、ゲームのアップストリーム帯域幅使用量を増加させる可能性があります。クラウド リレー サービスを介してゲームやボイス メッセージを送信するとき、Party はサービスに単一のメッセージを送信します。サービスは次にそのメッセージを複製して各ターゲット デバイスに転送します。ダイレクト ピアツーピア接続を介してゲームやボイス メッセージを送信するとき、Party はダイレクト ピアツーピア接続が確立された各ターゲット デバイスに対して直接接続を介してメッセージを複製して送信します。したがって、ゲームのアップストリーム帯域幅の使用量は、ダイレクト ピアツーピア接続が確立されたデバイス数に比例してスケーリングします。ダイレクト ピアツーピア接続を有効にする前に、このアップストリーム帯域幅の増加がゲームに許容できるかどうかを検討してください。

## ゲームでダイレクト ピアツーピア接続を使用する方法

### ネットワークでダイレクト ピアツーピア接続を有効にする

[`PartyManager::CreateNewNetwork()`](/services/playfab/multiplayer/networking/reference/classes/PartyManager/methods/partymanager_createnewnetwork) を介してネットワークを作成するとき、呼び出しに提供される [`PartyNetworkConfiguration`](/services/playfab/multiplayer/networking/reference/structs/partynetworkconfiguration) を通じてさまざまなネットワーク構成パラメーターを指定できます。`PartyNetworkConfiguration::directPeerConnectivityOptions` フィールドを使用して、ネットワーク内のデバイスに対してダイレクト ピアツーピア接続をサポートするかどうか、およびその方法を指定できます。

以下の例は、プラットフォーム タイプやログイン プロバイダーに関係なく、ネットワーク内のすべてのデバイス間でダイレクト ピアツーピア接続を試行する必要があると指定したネットワーク構成を示します。

```cpp theme={null}
PartyNetworkConfiguration configuration = {};
configuration.directPeerConnectivityOptions = PartyDirectPeerConnectivityOptions::AnyPlatformType | PartyDirectPeerConnectivityOptions::AnyEntityLoginProvider;
// Initialize the rest of the network configuration parameters appropriately for your game before using.
```

最初のユーザーがネットワークに認証を成功させた際に、ネットワーク構成で許可されている場合、デバイスはネットワークに既に参加している他のデバイスとダイレクト ピアツーピア接続を確立しようとする可能性があります。成功した試みでは、それらのデバイス間のエンドポイント メッセージとチャット データはそれらのダイレクト接続を使用して転送されます。デバイス間の環境の非互換性により試行が失敗した場合、それらのデバイス間のすべての通信は代わりに透過的なクラウド リレー サーバーを介して転送されます。ネットワーク構成でダイレクト ピア接続の試行が許可されていない場合、デバイスは IP アドレス情報を交換せず、常にエンドポイント メッセージとチャット データを透過的なクラウド リレー サーバーを介して送信します。

<Note>
  ダイレクト ピア接続の確立はベスト エフォートであり、環境的要因、デバイス単位の接続オプション、またはプラットフォーム ポリシーのために不可能な場合があります。特定のデバイスとのダイレクト ピアツーピア接続が確立されたかを評価する方法の詳細については、[接続タイプとレイテンシの評価](#evaluating-the-connection-type-and-latency) を参照してください。
</Note>

### デバイスごとにダイレクト ピア接続を制約する

ネットワーク構成のダイレクト ピア接続オプションに加えて、デバイスが認証するすべてのネットワークに対して、[`PartyManager::SetOption()`](/services/playfab/multiplayer/networking/reference/classes/PartyManager/methods/partymanager_setoption) を使用して [`PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask`](/services/playfab/multiplayer/networking/reference/enums/partyoption) を設定することで、デバイスによってダイレクト ピア接続をさらに制約できます。すべてのフラグはビット AND 演算を使用して評価されます。つまり、特定のネットワークのデバイス ペアに対して特定のフラグが有効となるのは、ネットワーク構成と両方のデバイスのそれぞれのローカル マスク オプションの 3 か所で有効になっている場合のみです。ネットワーク構成が関連する形式のダイレクト ピア接続を許可している場合でも、どちらのデバイスも自身のローカル デバイス マスク オプションでフラグを有効にしないことにより、IP アドレスの開示およびそれらの間のダイレクト接続試行から独立してオプトアウトできます。ダイレクト ピア接続をサポートするライブラリ バージョンでは、`PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask` の値は既定でネットワークが有効化するすべてのダイレクト ピア接続を許可します。したがって、ローカル デバイスに関連する一部またはすべてのダイレクト ピア接続を防ぐデバイス固有の要件がある場合にのみ構成する必要があります。

以下の例は、ローカル デバイスが同じプラットフォームのデバイスに対してのみダイレクト ピア接続を試行するように制約する方法を示しています。

```cpp theme={null}
PartyDirectPeerConnectivityOptions localDeviceMask = PartyDirectPeerConnectivityOptions::SamePlatformType | PartyDirectPeerConnectivityOptions::AnyEntityLoginProvider;
PartyError error = PartyManager::GetSingleton().SetOption(nullptr, PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask, &localDeviceMask);
if (PARTY_FAILED(error))
{
    printf("Failed to set local device direct peer connectivity options mask! error = 0x%08x\n", error);
}
```

### 接続タイプとレイテンシの評価

ローカル デバイスが特定のリモート デバイスとのダイレクト ピアツーピア接続を確立したかどうかは、[`PartyNetwork::GetDeviceConnectionType()`](/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_getdeviceconnectiontype) を呼び出すことで判定できます。

特定のペアのデバイス間でダイレクト ピアツーピア接続が利用可能であるかを積極的に強制しない (つまり、PartyNetwork::GetDeviceConnectionType() が [`PartyDeviceConnectionType::DirectPeerConnection`](/services/playfab/multiplayer/networking/reference/enums/partydeviceconnectiontype) 以外の値を報告する場合に [`PartyNetwork::LeaveNetwork()`](/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_leavenetwork) を呼び出さない) ことをお勧めします。使用中の特定の基礎となる転送方法は、通信する全体的な論理的能力を変更するものではないためです。ゲーム デザインに最大メッセージ レイテンシに関する厳しい要件があり、ダイレクト ピア接続を促進する場合、伝送メカニズムに基づいた抽象的な仮定を作るのではなく、[`PartyEndpointStatistic::AverageDeviceRoundTripLatencyInMilliseconds`](/services/playfab/multiplayer/networking/reference/enums/partyendpointstatistic) 統計で報告されるそのレイテンシの現在の具体的な観測に対して行動を起こすほうが良いです。そうしないと、環境要因により近くの透過的なクラウド リレー サーバーを常に使う必要のある、同じセットのフレンドとプレイしようとしているユーザーを継続的に妨げる可能性があります。

以下の例は、`network` 内の `localEndpoint` から `remoteEndpoint` へのラウンドトリップ レイテンシを検査する方法を示しています。

```cpp theme={null}
// A helper for inspecting the connection type and average round trip latency between a local endpoint and a remote
// endpoint in a network.
void PrintConnectionTypeAndLatency(
    PartyNetwork* network,
    PartyLocalEndpoint* localEndpoint,
    PartyEndpoint* remoteEndpoint
    )
{
    // Retrieve the device associated with the remote endpoint.
    PartyDevice* remoteDevice;
    PartyError error = remoteEndpoint->GetDevice(&remoteDevice);
    if (PARTY_FAILED(error))
    {
        printf("Failed to get the remote device! error = 0x%08x\n", error);
        return;
    }

    // Get the device connection type.
    PartyDeviceConnectionType connectionType;
    PartyError error = network->GetDeviceConnectionType(remoteDevice, &connectionType);
    if (PARTY_FAILED(error))
    {
        printf("Failed to get device connection type! error = 0x%08x\n", error);
        return;
    }

    // Retrieve the latency statistic.
    PartyEndpointStatistic latencyStatistic = PartyEndpointStatistic::AverageDeviceRoundTripLatencyInMilliseconds;
    uint64_t latencyStatisticValue;
    error = localEndpoint->GetEndpointStatistics(
        1,                       // targetEndpointCount
        &remoteEndpoint,         // targetEndpoints
        1,                       // statisticCount
        &latencyStatistic,       // statisticTypes
        &latencyStatisticValue); // statisticValues
    if (PARTY_FAILED(error))
    {
        printf("Failed to get latency statistic! error = 0x%08x\n", error);
        return;
    }

    // Print the results.
    printf("Local endpoint 0x%p and remote endpoint 0x%p in network 0x%p have average round trip latency %llu ms and device connection type %i\n",
        localEndpoint,
        remoteEndpoint,
        network,
        latencyStatisticValue,
        static_cast<int32_t>(connectionType));
}
```

### 接続タイプの変更

環境条件の変化により、ダイレクト ピア接続が中断され、PlayFab Party で使用不可能になる可能性があります。
これが起きると、デバイスはクラウド リレー サーバーを介した通信にフォールバックしようとします。中継された通信が引き続き可能である場合、[PartyNetwork::GetDeviceConnectionType()](/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_getdeviceconnectiontype) 関数は [PartyDeviceConnectionType::RelayServer](/services/playfab/multiplayer/networking/reference/enums/partydeviceconnectiontype) を報告し始め、デバイスは以降新しい接続タイプを使用して Party ネットワーク内に留まります。それ以外の場合、切断された接続を持つデバイスはネットワークから離れます。

<Warning>
  ダイレクト ピア接続が中断されたときに、そこで送受信中だったチャットおよびゲーム メッセージは、[PartySendMessageOptions::GuaranteedDelivery](/services/playfab/multiplayer/networking/reference/enums/partysendmessageoptions) を使用して送信された場合でも、また [PartyLocalEndpoint::GetEndpointStatistics()](/services/playfab/multiplayer/networking/reference/classes/PartyLocalEndpoint/methods/partylocalendpoint_getendpointstatistics) から返される [PartyEndpointStatistic::CurrentlyQueuedSendMessages](/services/playfab/multiplayer/networking/reference/enums/partyendpointstatistic) や [PartyEndpointStatistic::CurrentlyActiveSendMessages](/services/playfab/multiplayer/networking/reference/enums/partyendpointstatistic) の値でカウントされなくなっていた場合でも、決して到達しない場合があります。
</Warning>

また、接続タイプの遷移期間中に送信されたメッセージは、[PartySendMessageOptions::SequentialDelivery](/services/playfab/multiplayer/networking/reference/enums/partysendmessageoptions) を使用して送信された場合でも順序が入れ替わって到着する可能性があります。
タイトルは、ダイレクト ピア接続とこれらの PartySendMessageOptions を使用するときに、このデータ損失と順序の入れ替わりの可能性に備える必要があります。

PartyDeviceConnectionType::RelayServer の接続タイプは、その値がデバイスが最初にネットワークに参加したときに割り当てられたか、以前に切断されたダイレクト ピア接続の後に割り当てられたかに関係なく、他のタイプに変わることはありません。

## 課金メーター

ダイレクト ピアツーピア接続を使用するネットワークにも、クラウド リレー サービスを使用するネットワークと同じ [課金メーター](/services/playfab/pricing/meters/meters#party) が適用されます。ただし、クラウド リレー サービスを経由するゲームまたはボイス データのみが **Network egress** と **Party voice** のメーターに計上されます。


## Related topics

- [Workaround for peer-to-peer connection](/ja-jp/services/playfab/multiplayer/matchmaking/peer-to-peer.md)
- [セッションテンプレートの定数](/ja-jp/services/xbox-services/multiplayer/mpsd/concepts/live-session-template-constants.md)
- [PartyDirectPeerConnectivityOptions](/ja-jp/services/playfab/multiplayer/networking/reference/enums/partydirectpeerconnectivityoptions.md)
- [DirectPeerConnectivityOptions](/ja-jp/services/playfab/multiplayer/networking/unity-party-api-reference/enums/partyunitydirectpeerconnectivityoptions.md)
- [PartyNetwork::GetDeviceConnectionType](/ja-jp/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_getdeviceconnectiontype.md)
