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); } } } }