LoginSignup
4
4

More than 5 years have passed since last update.

Unity&iOS9&IPv6ネットワークでホスト名のないIPv4アドレスにSocketを使って接続する

Last updated at Posted at 2016-01-10

こちらの情報は2016/7/11時点のものです。現在の最新版では状況が変わっている可能性がありますのでご注意ください。

問題

2016/06/01からiOSアプリでのIPv6(NAT64)ネットワーク対応が義務化されましたが、
UnityでSocketを使って下記のようなコードを書いていた場合、NAT64ネットワークで接続に失敗してしまいます。

var addresses = Dns.GetHostAddresses(hostnameOrIP);
if (addresses.Length > 0) {
    var address = addresses[0];
    var socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
    var endPoint = new IPEndPoint(address, port);
    socket.Connect(endPoint);

    // socketを使った処理...
}

このプログラムをNAT64ネットワークで動かしてみると、

  • ホスト名を指定した場合(eg. hostnameOrIP="google.com")→ 問題なく動作する
  • IPv4アドレスを直接指定した場合(eg. hostnameOrIP = "216.58.220.206")→ エラーが発生する

ホスト名でしかサーバへ接続しない場合は問題ないのですが、いろいろな事情によりホスト名のないサーバへ接続しなければならない場合はなにか対処を行う必要があります。

Appleの上記リンクでの説明のよればgetaddrinfo関数をを使ってIPv4アドレスからIPv6アドレスをsynthesizeできるとのことです。しかしUnity C#上からはこの関数を直接呼び出すことができません。

対処

とりあえずなんらかの方法でgetaddrinfo関数を呼び出す必要があります。

方法1. getaddrinfoを呼び出すプラグインを作成する

Forumでプラグインを公開されてる方がいました。

これを使うことでC#上から間接的にgetaddrinfoを呼び出し、IPv6アドレスを得ることができます。

方法2. Dns.GetHostAddressesの代わりにDns.GetHostEntryDns.GetHostByNameなどのメソッドを使う

Dns.GetHostEntryDns.GetHostByNameは内部でgetaddrinfoを呼び出しているため、これらのメソッドを使うことでIPv6アドレスを得ることができます。
ただしこれについては下記のようなリスク・デメリットがあります。

  • 公式に保証された動作ではないため将来的に予期せず変更の可能性がある
  • Dns.GetHostEntryを呼び出すとDNS逆引処理が行われ、不要なオーバーヘッドが発生してしまう
  • Dns.GetHostByNameは現在Obsoleteである

そのため基本的には方法1を使うようにし、方法2については個人での開発でアップデートの予定がないときなど極めて限定的なケースでのみの使用にとどめておいたほうが良さそうです。

64:ff9b::/96をつける方法は駄目

なおMacのインターネット共有機能を使って作成したNAT64ネットワークでは、IPv4アドレスにプレフィックス64:ff9b::/96をつける方法でもうまく動作させることができます。
ただしこのプレフィックスはネットワークによっては異なる可能性があり、推奨されていません。

詳しくはApple Developer Forumsの下記ページの#4を参照してください。

はい

ところでiOS9環境にてC#上でIPv4アドレスからIPv6アドレスへ変換する方法について、Xamarinが何か言ってないか/公式で用意していないかと探したんですが見つけられませんでした。Xamarin.iOSのアプリもSocket使っていれば同じような問題に直面すると思うのですがどうなんでしょう?(試してない)(何か情報があれば教えてください)

Xamarinのアップデートで何か対応があったとしても、Unity側でそれが取り込まれるのははるか先のことだと思うのでおそらく意味ないのですが。

追記(2016/06/23)

Xamarinより言及がありました。

……が、言及されているMapToIPv6()が返すのは"IPv4-mapped address"で、Apple指定のNAT64環境で使える"synthesis"されたアドレスとは別のような? ちょっとよくわからないです。

どちらにしろUnityではMapToIPv6()は使えないのですが。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4