ピア クライアント用の高度な NAT テクニック
ピア クライアント用の高度な NAT テクニック
Microsoft® DirectPlay® は、ユニバーサル プラグ アンド プレイ (UPnP) をサポートしないネットワークアドレス変換 (NAT) デバイスの対象であるピア クライアントに対しては、100 パーセントの接続性を提供しない。しかし、アプリケーションでより複雑な手法を使うことで、このような状況でのサポートを向上できる可能性がある。ここで説明するテクニックには、より多くの開発作業と、外部サーバー リソースが必要になる。
NAT リゾルバ
NAT デバイスは、内部のコンピュータが外部のコンピュータにパケットを送信するときに、明示しないポート マッピングを作成する。NAT デバイスによっては、元の外部ターゲットが送信した応答を単に転送する代わりに、このポート マッピングを使った内部のコンピュータへの送信を、外部のコンピュータに対して許可するものがある。このような NAT は、"loose NAT" と呼ばれることがある。DirectPlay は、ピア ホストが NAT の対象でないときに、この動作を自動的に活用する。アプリケーションは、IDirectPlay8NATResolver インターフェイスとアドレス コンポーネントを使って、loose NAT の対象であるピア クライアントが、同じ NAT デバイスの対象である、ホスティングされたセッションに参加するようにできる。このとき、同じセッションに既に接続されている外部ピア クライアントを使う。
最初に、インターネットからアクセス可能な IDirectPlay8NATResolver サーバーを実装しなければならない。次に、ゲーム アプリケーションは、IDirectPlay8Peer::EnumHosts または IDirectPlay8Peer::Connect に渡すデバイス アドレスに、DPNA_KEY_NAT_RESOLVER コンポーネントを追加できる。このコンポーネント データは、インターネット プロトコル (IP) アドレスと、使用する NAT リゾルバのポートをコロンで区切った文字列である。たとえば、次のコードは、アドレス 123.123.123.123 のポート 5678 にあるサーバーを使うことを指定する。
WCHAR * wszNATResolver = L"123.123.123.123:5678";
DWORD dwNATResolverSize = (wcslen(wszNATResolver) + 1) * sizeof(WCHAR);
hr = pDP8DeviceAddress->AddComponent(DPNA_KEY_NAT_RESOLVER,
wszNATResolver,
dwNATResolverSize,
DPNA_DATATYPE_STRING);
また、次の例のように、数値の IP アドレスの代わりにホスト名を指定することもできる。
WCHAR * wszNATResolver = L"resolver.mydomain.com:5678";
DWORD dwNATResolverSize = (wcslen(wszNATResolver) + 1) * sizeof(WCHAR);
hr = pDP8DeviceAddress->AddComponent(DPNA_KEY_NAT_RESOLVER,
wszNATResolver,
dwNATResolverSize,
DPNA_DATATYPE_STRING);
信頼性を高めるために、複数の解決サーバーを試すことを勧める。次の例に示すように、複数のアドレスをコンマで区切って指定できる。
WCHAR * wszNATResolvers = L"123.123.123.123:5678,backupresolver.mydomain.com:6789";
DWORD dwNATResolverSize = (wcslen(wszNATResolvers) + 1) * sizeof(WCHAR);
hr = pDP8DeviceAddress->AddComponent(DPNA_KEY_NAT_RESOLVER,
wszNATResolvers,
dwNATResolverSize,
DPNA_DATATYPE_STRING);
各リゾルバの速度が同時にテストされ、最初の応答が使われる。サーバーが応答しない場合でも、IDirectPlay8Peer::EnumHosts または IDirectPlay8Peer::Connect 呼び出しは成功する。
これらの解決サーバーをホストとするにはリソースが必要なため、任意のプレーヤがリゾルバを使わないように設定できる。そのためには、DPNA_KEY_NAT_RESOLVER_USER_STRING アドレス コンポーネントを使う。この値は、DPN_MSGID_NAT_RESOLVER_QUERY メッセージでの確認のためにリゾルバに直接渡され、必要に応じて応答または無視する選択ができる。次のサンプル コードは、この設定方法を示している。
WCHAR * wszPassword = L"MyPassword";
DWORD dwPasswordSize = (wcslen(wszPassword) + 1) * sizeof(WCHAR);
hr = pDP8DeviceAddress->AddComponent(DPNA_KEY_NAT_RESOLVER_USER_STRING,
wszPassword,
dwPasswordSize,
DPNA_DATATYPE_STRING);
注 ユーザー文字列はネットワークを介してクリア テキストで渡される。したがって、テキストに重要情報が含まれている可能性がある場合、何らかの形式で暗号化すること。
ピア クライアントの NAT デバイスが、NAT リゾルバ クエリーのポート マッピングを生成する。NAT リゾルバがクエリーに応答することを選択した場合、DirectPlay はそのマッピングのパブリック アドレスを元のピア クライアントに送信する。次に、外部のピア クライアントが、参加する内部クライアントと通信できるようにセッションに接続するときに、アドレスがホストに報告される。
NAT リゾルバ アドレス コンポーネントの使用例は、NATPeer サンプルで説明している。