はじめに
アプリ開発をしている際に、サーバーとのネットワークを接続状態をチェックする必要がありましたが、サーバー名(ホストネーム)からIPアドレスを取得しなければいけませんでした。
マイクロソフトのドキュメントにDns.GetHostEntry メソッドがありそれを参考に作成しました。
そこにこんなサンプルがありました。
// ホストネームからアドレスを取得する
public static void DoGetHostEntry(string hostname)
{
IPHostEntry host = Dns.GetHostEntry(hostname);
Console.WriteLine($"GetHostEntry({hostname}) returns:");
foreach (IPAddress address in host.AddressList)
{
Console.WriteLine($" {address}");
}
}
問題点
このサンプルだと、ホストネームからアドレスを取得した際に、ipv6とipv4の両方を取得してしまいました。
自分が作成していたアプリでは、取得したアドレスをもとにpingでネットワークを確認するようにしていましたが、ipv6は時間がかかり、パフォーマンスに問題が起きてしまいました。
/// <summary>
/// 指定されたIPアドレスのPingを確認する
/// </summary>
/// <param name="arg"></param>
/// <returns></returns>
private bool CheckPing(object arg)
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
// Use the default Ttl value which is 128,
// but change the fragmentation behavior.
options.DontFragment = true;
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 25;
PingReply reply = pingSender.Send(arg.ToString(), timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
return true;
}
return false;
}
解決方法
サンプルで取得できたhost.AddressListのうち、どれがipv4か確認する方法がわかればいいです。
調べるとIPAddress.AddressFamily プロパティというものがありました。それを見ると、「IPv4 の場合は InterNetwork、IPv6 の場合は InterNetworkV6 を返します」とありました。
これを参考にして以下のようにサンプルを書き換えました。
private IPAddress DoGetHostEntry(string hostname)
{
IPHostEntry host = Dns.GetHostEntry(hostname);
foreach (IPAddress address in host.AddressList)
{
if (address.AddressFamily == AddressFamily.InterNetwork)
return address;
}
return null;
}
これで問題なくipv4のアドレスを取得して、ping確認することができるようになりました。