/// <summary>查询</summary> /// <param name="request"></param> /// <param name="remoteEndPoint"></param> /// <returns></returns> public StunMessage Query(StunMessage request, IPEndPoint remoteEndPoint) { EnsureSocket(); return(Query(Socket, request, remoteEndPoint)); }
///// <summary>在指定服务器上执行查询</summary> ///// <param name="host"></param> ///// <param name="port"></param> ///// <returns></returns> //public StunResult QueryWithServer(String host, Int32 port = 3478) //{ // try // { // return QueryWithServer(NetHelper.ParseAddress(host), port); // } // catch { return null; } //} /// <summary>在指定服务器上执行查询</summary> /// <param name="address"></param> /// <param name="port"></param> /// <returns></returns> public StunResult QueryWithServer(IPAddress address, Int32 port) { EnsureSocket(); var client = Socket as ISocketClient; var remote = new IPEndPoint(address, port); // Test I // 测试网络是否畅通 var msg = new StunMessage { Type = StunMessageType.BindingRequest }; var rs = Query(client, msg, remote); // UDP blocked. if (rs == null) { return(new StunResult(StunNetType.Blocked, null)); } WriteLog("服务器:{0}", rs.ServerName); WriteLog("映射地址:{0}", rs.MappedAddress); WriteLog("源地址:{0}", rs.SourceAddress); WriteLog("新地址:{0}", rs.ChangedAddress); var remote2 = rs.ChangedAddress; // Test II // 要求改变IP和端口 msg.ChangeIP = true; msg.ChangePort = true; msg.ResetTransactionID(); // 如果本地地址就是映射地址,表示没有NAT。这里的本地地址应该有问题,永远都会是0.0.0.0 //if (client.LocalEndPoint.Equals(test1response.MappedAddress)) var pub = rs.MappedAddress; if (pub != null && client.Local.Port == pub.Port && pub.Address.IsLocal()) { // 要求STUN服务器从另一个地址和端口向当前映射端口发送消息。如果收到,表明是完全开放网络;如果没收到,可能是防火墙阻止了。 rs = Query(client, msg, remote); // Open Internet. if (rs != null) { return(new StunResult(StunNetType.OpenInternet, pub)); } // Symmetric UDP firewall. return(new StunResult(StunNetType.SymmetricUdpFirewall, pub)); } else { rs = Query(client, msg, remote); if (rs != null && pub == null) { pub = rs.MappedAddress; } // Full cone NAT. if (rs != null) { return(new StunResult(StunNetType.FullCone, pub)); } // Test II msg.ChangeIP = false; msg.ChangePort = false; msg.ResetTransactionID(); // 如果是Tcp,这里需要准备第二个重用的Socket if (client.Local.IsTcp) { EnsureSocket2(); client = Socket2 as ISocketClient; } rs = Query(client, msg, remote2); // 如果第二服务器没响应,重试 if (rs == null) { rs = Query(client, msg, remote2); } if (rs != null && pub == null) { pub = rs.MappedAddress; } if (rs == null) { return(new StunResult(StunNetType.Blocked, pub)); } // 两次映射地址不一样,对称网络 if (!rs.MappedAddress.Equals(pub)) { return(new StunResult(StunNetType.Symmetric, pub)); } // Test III msg.ChangeIP = false; msg.ChangePort = true; msg.ResetTransactionID(); rs = Query(client, msg, remote2); if (rs != null && pub == null) { pub = rs.MappedAddress; } // 受限 if (rs != null) { return(new StunResult(StunNetType.AddressRestrictedCone, pub)); } // 端口受限 return(new StunResult(StunNetType.PortRestrictedCone, pub)); } }