WindowsでTCP/IPのプログラムを作ったときに名前解決を早くする
昨日の実験の結果では、WindowsのTCP/IPプログラミングではローカルネットワーク上のホスト名を名前解決をしようとしたときに、getaddrinfo()で1秒待たされてしまっていました。
長い間の試行錯誤の末、この「名前解決で1秒待たされる動作」を解決する方法がわかりました。
普通にgetaddrinfoを使ったプログラムは、
struct addrinfo hints, * res;
memset(&hints, 0, sizeof(hints));
int err = getaddrinfo(host, NULL , &hints, &res);
のようになります。
getaddrinfo()にはこれといってオプションがないように見えるのですが、よく見たらhintsという引数があって、どんな体系のアドレスで解決するかのヒントを与えることができるようです。
これには全部ゼロである構造体を入れてもよいのですが、hints.ai_family = AF_INET;と指定すると、1秒待たされる動作をしなくなることがわかりました。
struct addrinfo hints, * res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
int err = getaddrinfo(host, NULL , &hints, &res);
これは、AF_INET、つまりIPv4の範囲内で名前解決をしなさいとヒントを与えているわけです。
デバッガで実行してみると
29ミリ秒でgetaddrinfoが終了しています。
このような指定をしてもMDNSのパケットはIPv4とIPv6の両方で出るのですが、AAAAレコードの問い合わせをしなくなります。
逆に、AF_INET6だけを指定するとAAAAレコードでの問い合わせだけが出るようになって1秒待たされます。
実はわざわざプログラムを組まなくてもPINGコマンドで同様の実験ができます。
PING -6 ホスト名
とやると、AAAAレコードを使ったIPv6アドレスの解決のみを行い、
PING -4 ホスト名
とやると、Aレコードを使ったIPv6アドレスの解決のみを行います。
つまり、Windowsは、ZYNQ Linuxのavahi-daemonが返したMDNSのレスポンスの何かが気に入らなくて1秒間タイムアウトしていたと考えられます。
根本的な解決はまだですが、getaddrinfoの前にIPv4で解決する
hints.ai_family = AF_INET;
を付けるだけで、getaddrinfo()で待たされる時間が大幅に減り、アプリの起動時間が短縮できました。
| 固定リンク
コメント