.net 动力壳;为什么此代码总是返回';正确';即使没有IPv6?错了吗?
不是powershell专家,但作为Windows 10小项目的一部分,正在检查IPv6连接。这(下面的代码)就是我正在使用的,如果可能的话,我想继续使用它,因为它速度快,并且不涉及某个网站返回公共视图IPv6地址。使用的远程IPv6地址(2001:4860:4860::8888)是Google公共IPv6 DNS。我从一些代码中得到了这个想法,其中Google Ipv6 DNS服务器用于检查Chrome中的全局Ipv6连接.net 动力壳;为什么此代码总是返回';正确';即使没有IPv6?错了吗?,.net,powershell,udp,.net,Powershell,Udp,不是powershell专家,但作为Windows 10小项目的一部分,正在检查IPv6连接。这(下面的代码)就是我正在使用的,如果可能的话,我想继续使用它,因为它速度快,并且不涉及某个网站返回公共视图IPv6地址。使用的远程IPv6地址(2001:4860:4860::8888)是Google公共IPv6 DNS。我从一些代码中得到了这个想法,其中Google Ipv6 DNS服务器用于检查Chrome中的全局Ipv6连接 它的问题是,即使在接口适配器上禁用IPv6并禁用Teredo,当它不应
它的问题是,即使在接口适配器上禁用IPv6并禁用Teredo,当它不应该连接时,它仍然返回“True”(即其已连接)。如果接口适配器上没有启用IPv6,或者IPv6在防火墙或通过其他方式被阻止,我希望它返回“False”。我做错了什么 UDP协议是无连接的。所以,“连接”状态对它没有实际意义,不像TCP(我怀疑您只收到硬编码的存根值)。然后,您可以尝试从一开始就切换到DNS请求的TCP版本(尽管RFC建议仅当UDP响应包含“截断”标志时才使用TCP DNS)。再看一看,我们可以看到它在做什么 TL;DR,它检查机器是否实际分配了有效的非本地、非隧道式ipv6地址 关键函数(或方法,它是C++)是 它从一个带有函数头的锅炉板、一个跟踪函数和一个UDP套接字指针的创建开始
// Attempts to connect a UDP socket to |dest|:53.
bool IsGloballyReachable(const IPAddress& dest,
const NetLogWithSource& net_log) {
// TODO(eroman): Remove ScopedTracker below once crbug.com/455942 is fixed.
tracked_objects::ScopedTracker tracking_profile_1(
FROM_HERE_WITH_EXPLICIT_FUNCTION("455942 IsGloballyReachable")
);
std::unique_ptr<DatagramClientSocket> socket(
ClientSocketFactory::GetDefaultFactory()->CreateDatagramClientSocket(
DatagramSocket::DEFAULT_BIND,
RandIntCallback(),
net_log.net_log(),
net_log.source()
)
);
如果失败了,那就是我们的回报
这就是powershell代码停止的地方
但我们还没做完
下一个测试:我们可以得到套接字的本地地址吗
IPEndPoint endpoint;
rv = socket->GetLocalAddress(&endpoint);
if (rv != OK)
return false;
如果行得通,我们就开始检查实际地址
DCHECK_EQ(ADDRESS_FAMILY_IPV6, endpoint.GetFamily());
const IPAddress& address = endpoint.address();
我们首先消除本地地址的链接:
bool is_link_local =
(address.bytes()[0] == 0xFE) && ((address.bytes()[1] & 0xC0) == 0x80);
if (is_link_local)
return false;
我们消除了带有teredo前缀的地址
const uint8_t kTeredoPrefix[] = {0x20, 0x01, 0, 0};
if (IPAddressStartsWith(address, kTeredoPrefix))
return false;
其他任何内容都假定为全局地址空间中的有效本地ipv6地址:
return true;
}
这实际上是在测试全球连通性吗?不,因为你实际上并没有发送任何数据包,所以不会看到是否有防火墙会阻止你的流量。但它验证至少一个网络接口具有有效的非本地ipv6地址
要复制此测试,您需要检查连接的网络接口是否为ipv6地址。粗略地看一下chromium代码片段,我发现它实际上向Google公共DNS解析程序发送了一个DNS数据包,只有在收到响应时才返回true。上面的代码只创建了一个udp6套接字并停在那里。我一开始也是这么想的,但从我想到的链接中读到的是“(注意,检查的结果实际上没有发送任何数据包;UDP不需要发送任何数据包来连接,HostResolverImpl也不显式地通过套接字发送任何数据)。”从:
如果在用户数据报协议(UDP)套接字上调用Connect,则Connected属性始终返回true;但是,此操作不会改变UDP固有的无连接特性。
Ahhh-HA!所以它总是会返回真的,如果它实际连接或没有,如果它的UDP。嗯,我想这就是答案。我没想过,但也许。我想知道它是如何在Chrome代码中正确工作的,但是当同样的东西在Powershell中创建时,它就失败了@约翰:这个问题与PowerShell per无关;这就是System.Net.Sockets.Socket
.Net类的设计方式:“action”一词可能会让人困惑;他们的意思是,即使属性声明连接状态,连接的概念实际上并不适用于无连接的UDP协议。我误认为它实际上是在检查Ipv6全球连接,而实际上它所做的基本上是检查全球Ipv6地址是否可用。很好的总结。我应该补充一点,即tl;博士
const uint8_t kTeredoPrefix[] = {0x20, 0x01, 0, 0};
if (IPAddressStartsWith(address, kTeredoPrefix))
return false;
return true;
}