IEnumerable <StunResult> QueryByServers() { // 如果是被屏蔽,很有可能是因为服务器没有响应,可以通过轮换服务器来测试 StunResult result = null; foreach (var item in Servers) { WriteLog("使用服务器:{0}", item); //Int32 p = item.IndexOf(":"); //if (p > 0) // result = QueryWithServer(item.Substring(0, p), Int32.Parse(item.Substring(p + 1))); //else // result = QueryWithServer(item, 3478); var ep = NetHelper.ParseEndPoint(item, 3478); try { result = QueryWithServer(ep.Address, ep.Port); } catch { result = null; } yield return(result); } }
/// <summary>确保建立服务器</summary> public override void EnsureCreateServer() { if (Servers.Count <= 0) { // 同时两个端口 AddServer(IPAddress.Any, Port, ProtocolType.Unknown, AddressFamily.InterNetwork); AddServer(IPAddress.Any, Port2, ProtocolType.Unknown, AddressFamily.InterNetwork); var dic = new Dictionary <Int32, IPEndPoint>(); IPEndPoint ep = null; var pub = NetHelper.MyIP(); StunResult rs = null; WriteLog("获取公网地址……"); foreach (var item in Servers) { if (item.Local.ProtocolType == ProtocolType.Tcp) { continue; } // 查询公网地址和网络类型,如果是受限网络,或者对称网络,则采用本地端口,因此此时只能依赖端口映射,将来这里可以考虑操作UPnP if (rs == null) { item.Start(); rs = new StunClient(item).Query(); if (rs != null) { if (rs != null && rs.Type == StunNetType.Blocked && rs.Public != null) { rs.Type = StunNetType.Symmetric; } WriteLog("网络类型:{0} {1}", rs.Type, rs.Type.GetDescription()); ep = rs.Public; if (ep != null) { pub = ep.Address; } } } else { ep = new StunClient(item).GetPublic(); } if (rs != null && rs.Type > StunNetType.AddressRestrictedCone) { ep = new IPEndPoint(pub, item.Port); } WriteLog("{0}的公网地址:{1}", item.Local, ep); dic.Add(item.Port, ep); } // Tcp没办法获取公网地址,只能通过Udp获取到的公网地址加上端口形成,所以如果要使用Tcp,服务器必须拥有独立公网地址 foreach (var item in Servers) { if (item.Local.ProtocolType != ProtocolType.Tcp) { continue; } ep = new IPEndPoint(pub, item.Port); WriteLog("{0}的公网地址:{1}", item.Local, ep); dic.Add(item.Port + 100000, ep); } //var ep = StunClient.GetPublic(Port, 2000); //WriteLog("端口{0}的公网地址:{1}", Port, ep); //dic.Add(Port, ep); //ep = StunClient.GetPublic(Port2, 2000); //WriteLog("端口{0}的公网地址:{1}", Port2, ep); //dic.Add(Port2, ep); WriteLog("成功获取公网地址!"); Public = dic; } }