using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace XGame.Framework.Network
{
///
/// 域名解析
///
public class SessionAddress
{
private enum InputType
{
Unknown,
Domain,
IPV4,
IPV6
}
private InputType _type = InputType.Unknown;
public string IP { get; private set; }
public int PORT { get; private set; }
public string URI { get; private set; }
public bool IsIpv6
{
get { return _type == InputType.IPV6; }
}
///
/// 域名或者IP
///
public string Domain { get; private set; }
public ProtocolType ProtocolType { get; private set; }
private const int TimeOut = 4000;
public SessionAddress(AddressInfo info)
{
Domain = info.Address;
PORT = info.Port;
ProtocolType = info.ProtocolType;
URI = info.Uri;
_type = InputType.Domain;
//尝试转换IP地址
//IPAddress.TryParse内部会取传入的值转成整数,然后转成ip地址
//这样传入8,解析出来的就是0.0.0.8
if (IPAddress.TryParse(Domain, out IPAddress address))
{
switch (address.AddressFamily)
{
case AddressFamily.InterNetwork:
{
_type = InputType.IPV4;
IP = Domain;
}
break;
case AddressFamily.InterNetworkV6:
{
_type = InputType.IPV6;
IP = Domain;
}
break;
}
}
}
///
/// 异步解析,如果构造的是域名,必须先调用此方法进行解析
/// 若忘记调用此方法进行解析,会导致不可预期的错误
/// callback 解析完毕回调,切记此处回调是线程!!
///
public void ParseDnsAsync(Action callback)
{
if (_type == InputType.Domain && string.IsNullOrEmpty(IP))
{
Task.Factory.StartNew(() =>
{
try
{
var task = Dns.GetHostEntryAsync(Domain);
if (!task.Wait(TimeOut))
{
Log.Warn($"[Net] Address parse timeout. Domain:{Domain}");
callback?.Invoke(this);
}
else
{
var ipHostEntry = task.Result;
if (ipHostEntry.AddressList.Length > 0)
{
IPAddress address = ipHostEntry.AddressList[0];
if (address.AddressFamily == AddressFamily.InterNetwork)
{
_type = InputType.IPV4;
IP = address.ToString();
}
else if (address.AddressFamily == AddressFamily.InterNetworkV6)
{
_type = InputType.IPV6;
IP = address.ToString();
}
else
{
Log.Warn($"[Net] Address family error. Domain:{Domain} Family:{address.AddressFamily}");
}
}
else
{
Log.Warn($"[Net] No Address. Domain:{Domain}");
}
callback?.Invoke(this);
}
}
catch (Exception e)
{
Log.Exception($"[Net] Address parse error. Domain:{Domain}", e);
callback?.Invoke(this);
}
});
}
else
{
callback?.Invoke(this);
}
}
}
}