英語で読む

次の方法で共有


優先ローカル ユーザー データグラム プロトコル (UDP) マルチプレイヤー ポート ネットワーク API

このトピックを使用すると、優先ローカル ユーザー データグラム プロトコル (UDP) マルチプレイヤー ポート ネットワーク API を使用してマルチプレイヤーの信頼性を向上させる方法を学ぶことができます。 Xbox 本体のすべてのイテレーションで UDP 3074 を使用できます。 これは公開登録されている、マルチプレイヤー ネットワーク トラフィック用のよく知られたポートです。 Microsoft Game Development Kit (GDK) のタイトルも例外ではなく、この特別なポートにアクセスするには、優先ローカル UDP マルチプレイヤー ポート ネットワーク API を使用します。

優先ローカル UDP マルチプレイヤー ポートは、リモート デバイスによってローカル デバイスとの接続に使用される場合があるパブリック ポートとは異なり、後続のソケットのバインド 処理に使用されるローカル ポートです。 これは UDP トラフィックに対してのみ効果的であり、伝送制御プロトコル (TCP) や HTTP トラフィックに対しては効果的ではありません。なぜなら、マルチプレイヤーのリアルタイムなタイトル ネットワーキング フローだけをターゲットとしているためです。

従来、このポートは UDP 3074 に限定されてきました。 しかし近年、このポートの信頼性を向上させるため、フォールバック ロジックが導入されるようになりました。 また、ユーザーがポートを手動で構成して、独自のネットワーク構成を操作できるようになりました。 このため、Microsoft Game Development Kit (GDK) タイトルで UDP 3074 をハードコーディングすることは安全ではなくなりました。 代わりに、Microsoft Game Development Kit (GDK) タイトルは、現在構成されているポートに対して動的にクエリを実行する必要があります。

優先ローカル UDP マルチプレイヤー ポートを取得するには、3 つの方法があります。

これら 3 つの方法では、いずれも同じ基本機能が提供されます。 いずれも (またはいずれの組み合わせも)、固有のニーズやユースケースに応じて、Microsoft Game Development Kit (GDK) タイトルから呼び出すことができます。

すべての Microsoft Game Development Kit (GDK) タイトルでは、メインのゲーム トラフィックに優先ポートを使用することを強くお勧めします。 このポートは、ピア ツー ピア ネットワーク トポロジとクライアント/サーバー ネットワーク トポロジの両方に最適化されています。 Microsoft Game Development Kit (GDK) プラットフォームは、この特定のポートが各ユーザーの特定のネットワーク環境に最も役立つと期待されるポートであることを確認します。 この特定のポートを使用すると、プラットフォームのカスタマー サポートと診断フローを最大限に利用して、標準化されたネットワーク アドレス変換 (NAT) の互換性を高め、標準化された UPnP™ 認定デバイス機能を提供し、サービス品質 (QoS) ルーターと ISP アルゴリズムに依存するリアルタイムのパケットを特定できます。

この優先ポートは、ピア ツー ピア ネットワーク トポロジに依存しているタイトルに特に適しています。 ファイアウォール パンチングを実行しないでファイアウォールを通過する受信 UDP パケットを許可する唯一のポートです。 Microsoft Game Development Kit (GDK) でピア ツー ピア ネットワーク トポロジに依存しているタイトルは、モデレイトまたはストリクト NAT タイプを持つクライアント用の NAT パンチング ソリューションと併せて、専用のパブリック IP アドレスとポート検出を提供することを期待されています。 優先ポートによって、これらのテクノロジの成功率は向上しますが、これらのテクノロジに代わるものではありません。

クライアント/サーバー ネットワーク トポロジを利用するタイトルでも、このポートを使用する利点があります。 トラブルシューティング、UPnP™、およびパケットの識別は、現在も、病院、ホテル、大学の寮で共通するキャプティブ ポータルおよびその他のソース ベースのフィルタリング手法に適しています。

優先ポートは他のすべてのポートと同じように扱う必要があります。 Windows ソケット 2 (Winsock) API と組み合わせて使用してください。 タイトルはこのポートの IPv4 と IPv6 の両方にバインドされるか、デュアルスタック ソケットを使用して INADDR_ANY/in6addr_any にバインドされる必要があります。

ソケット障害の処理

返されたポートを使用して、特定のサーバーやピアとのソケット接続を正常に確立できるという保証はありません。 通常のタイトルでは、操作が再試行され、フォールバック ロジックが実行されます。 ソケットが閉じて再度開かれた場合、タイトルはその都度、直近の優先ローカル UDP マルチプレイヤー ポートを再度クエリする必要があります。これは、ポートが時間の経過と共に変更される可能性があるためです。

ネットワークの初期化

XNetworkingQueryPreferredLocalUdpMultiplayerPort API の 3 つすべてのバリアント (ブロック、非同期、および通知ベース) は、タイトルの起動時および再開時にネットワークが初期化されるまで、完了/通知をブロックまたは遅延します。 ネットワーク初期化ステータスの検出の概要に従ってネットワーク初期化を個別に待機するか、これらの API を呼び出して、それらが戻るのを待つことができます。

一時停止と再開

他のソケットと同様に、優先ローカル UDP マルチプレイヤー ポートにバインドされているソケットは、ネットワークの初期化を待った後、サスペンド時に閉じ、レジューム時に再作成する必要があります。 RegisterAppStateChangeNotification を使用して、一時停止および再開のイベントに登録する必要があります。 再開時には、優先ローカル UDP マルチプレイヤー ポートが変更され、優先ローカル UDP マルチプレイヤー ポートへの変更をリッスンするか、新しいソケットを作成するときに再クエリを実行していると想定する必要があります。 WinSock の中断と再開の処理の詳細については、「Winsock での中断と再開」を参照してください。

優先ローカル UDP マルチプレイヤー ポートの変更

タイトルでは、XNetworkingRegisterPreferredLocalUdpMultiplayerPortChanged API を使用して、優先ローカル UDP マルチプレイヤー ポートの変更をリッスンすることができます。

これらの試行はすべて、タイトルの実行中に優先ローカル UDP マルチプレイヤー ポートが変更されないようにするためのものです。 ただし、ユーザーの外部ネットワーク状態が変化して既存のソケット フローが無効になった場合は、ポートが変更されることは避けられません。 特に、ネットワーク接続レベルが変化したり、タイトルの一時停止/再開が発生した場合には、ポートが変更される可能性が高くなります。

優先ローカル UDP マルチプレイヤー ポートが変更された場合、その後のピアからの追加受信接続が以前の優先ポートでブロックされる可能性があります。 その場合でも、ソケット層でエラーが発生しない場合があります。 ただし、タイトルでは、以前の優先ポートにバインドされたソケットでのパケット受信がやがて停止する場合があります。

既存のピアとの間で送受信されるパケットは引き続き機能する場合があります。 優先ローカル UDP マルチプレイヤー ポートの変更に関する通知があったとしても、進行中のゲーム セッションに致命的な影響はない可能性もあります。

変更通知が発生した場合、タイトルは新しい優先ポートにバインドされた新しいソケットに移行する必要があります。 この移行は、既存のゲームプレイを中断させることなく、できるだけ早いタイミングで実行される必要があります。 接続の喪失を検出し、ソケット接続を再試行するには、タイトルで常に最新の優先ポートを使用する必要があります。

優先ローカル UDP マルチプレイヤー ポートの変更をテストする

優先ローカル UDP マルチプレイヤー ポートを変更するには、次の手順を使用します。

  1. ゲームの実行中に、Xbox Guide を開きます。 [設定] アプリに移動します。
  2. [一般] タブで、[ネットワーク設定] を選択します。
  3. [詳細設定] を選択し、[代替ポートの選択] を選択します。
  4. ポートの選択を [手動] に設定します。 ポートを選択するには、ドロップダウン メニューを使用します。
  5. ポートの選択は直ちに適用され、対応する通知がタイトルに送信されます。
  6. テストが完了したらポートの選択を [自動] に戻して、ポートの動作を既定値に戻します。

注意

[設定] アプリの使用中は、タイトルは制限されていますが実行されており、タイトルが表示されていない場合でも、ポート変更通知をすぐに受け取ります。 タイトルに切り替えずに、[設定] アプリを 10 分以上開いたままにすると、タイトルは一時停止されます。

セキュリティ

優先ローカル UDP マルチプレイヤー ポートにバインドされたソケットは、他のソケットと同じように動作します。 追加のセキュリティは提供されません。 タイトルは、通信セキュリティのベスト プラクティスで指定されているように、優先ローカル UDP マルチプレイヤー ポートにバインドされているソケットの上に、独自のセキュリティで保護された通信プロトコルを使用する必要があります。 詳細については、「通信セキュリティの概要 (NDA トピック)認可が必須です」を参照してください。

ピア ツー ピア

優先ローカル UDP マルチプレイヤー ポートでは、ピアツーピア メッシュを作成できる最善のポートが提供されます。 ユーザーの NAT レイヤーを通じて受信接続ができるように、最善の方法で構成されています。 ただし、NAT トラバーサル (次を含む) はタイトル側で実行する必要があります。

  • NAT タイプの検出
  • デバイスのパブリック IP アドレスとポートの検出と交換
  • NAT のパンチングとトラバーサル

Azure PlayFab Party

内部的には、PlayFab Party では優先ローカル UDP マルチプレイヤー ポートが既定で使用されます。 これは、PlayFab Party API を通じて構成することができます。 PlayFab Party ポートが変更されない限り、タイトルを優先ローカル UDP マルチプレイヤー ポートに直接バインドさせないでください。

使用例

次の例は、デュアル スタック ソケットを優先ローカル UDP マルチプレイヤー ポートにバインドする方法を示したものです。 この例では、簡略化のためにブロッキングの XNetworkingQueryPreferredLocalUdpMultiplayerPort 呼び出しを使用しています。また、タイトルが以前にネットワークの準備ができるまで待機し、WSAStartup が既に呼び出されていることを前提としています。

HRESULT
CreateAndBindMultiplayerSocket(
    _Out_ SOCKET* multiplayerSocket
    )
{
    HRESULT hr;
    SOCKET resultSocket = INVALID_SOCKET;

    uint16_t port;
    hr = XNetworkingQueryPreferredLocalUdpMultiplayerPort(&port);
    if (FAILED(hr))
    {
        goto Failure;
    }

    resultSocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
    if (resultSocket == INVALID_SOCKET)
    {
        hr = HRESULT_FROM_WIN32(WSAGetLastError());
        goto Failure;
    }

    // Enable both IPv4 and IPv6 on this socket.
    int v6only = 0;
    if (setsockopt(resultSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&v6only, sizeof(v6only)) == SOCKET_ERROR)
    {
        hr = HRESULT_FROM_WIN32(WSAGetLastError());
        goto Failure;
    }

    sockaddr_in6 sa;
    ZeroMemory(&sa, sizeof(sa));
    sa.sin6_family = AF_INET6;
    sa.sin6_port = htons(port);
    sa.sin6_addr = in6addr_any;
    if (bind(resultSocket, (const sockaddr*)&sa, sizeof(sa)) == SOCKET_ERROR)
    {
        hr = HRESULT_FROM_WIN32(WSAGetLastError());
        goto Failure;
    }

    *multiplayerSocket = resultSocket;

Exit:

    return hr;

Failure:

    if (resultSocket != INVALID_SOCKET)
    {
        (void)closesocket(resultSocket);
    }

    goto Exit;
}

関連項目

優先ローカル UDP マルチプレイヤー ポート API のリファレンス (XNetworking)

Windows ソケット 2 (Winsock)

通信セキュリティの概要 (NDA トピック)認可が必須です