Windows通过NCSI组件判断是否真实联网:先DNS解析dns.msftncsi.com并验证返回IP,再HTTP请求www.msftncsi.com/ncsi.txt并校验响应内容,双成功才判定为有Internet访问。

怎么判断 Windows 当前是否联网,且不是假连(比如连着但没外网)?
直接调用 InternetGetConnectedState 是最轻量、最常用的方式,但它只告诉你“物理/协议层是否连上了”,比如插着网线或连上 Wi-Fi 就返回 true,哪怕 DNS 被劫持、网关失联、防火墙全拦,它也照常返回已连接。真正需要的,是确认能否访问公网(比如能解析 dns.google、能连通 8.8.8.8:53 或 https://www.msftconnecttest.com/redirect)。Windows 10+ 提供了更靠谱的替代:使用 NetworkInformation.GetInternetConnectionProfile()(C++/WinRT)或 INetworkListManager::GetConnectivity()(COM),但后者已被标记为 deprecated。
用 C++/WinRT 获取真实网络连通性(推荐 Win10 1809+)
这是目前最贴近系统原生感知逻辑的方式,能区分「无网络」「局域网」「有互联网」等状态,且自动考虑计量网络、飞行模式、代理设置等上下文。
关键步骤:
- 确保项目启用 C++/WinRT 支持(VS2019+ 默认开启,需在项目属性中确认
Consume Windows Runtime Extensions设为 Yes) - 包含头文件:
#include <winrt></winrt> - 调用
Windows::Networking::Connectivity::NetworkInformation::GetInternetConnectionProfile(),返回值为ConnectionProfile对象;若返回空,则当前无活跃网络配置 - 对非空对象调用
.GetNetworkConnectivityLevel(),返回值为NetworkConnectivityLevel枚举:
NetworkConnectivityLevel::None → 完全离线NetworkConnectivityLevel::LocalAccess → 仅局域网(如连着但没网关/DNS)NetworkConnectivityLevel::InternetAccess → 可访问公网(系统已验证 DNS + 连通性)
为什么不能只 ping 8.8.8.8 或 curl google.com?
这类手动探测看似直观,但会绕过系统网络栈的真实策略,导致误判:
立即学习“C++免费学习笔记(深入)”;
- 企业环境常禁 ping,ICMP 被拦截不等于不能上网
- 防火墙可能放行 HTTPS 但封掉 ICMP 或 DNS 查询
- 系统级网络感知(如 Windows 的 NCSI)会主动检查
http://www.msftconnecttest.com/connecttest.txt并比对响应内容,还校验 HTTP 状态码和 body 是否为预期字符串 —— 这才是 Windows 判断“有互联网”的标准动作 - 手动发起请求无法感知计量网络、按流量计费状态、或系统代理配置(比如 IE 代理开启但你的程序没走)
兼容旧系统(Win7/Win8)的降级方案
如果必须支持 Win7,InternetGetConnectedState 是唯一可用 API,但务必配合二次验证:
- 先调用
InternetGetConnectedState(&dwFlags, 0),若返回 false,可确定离线 - 若返回 true,再尝试异步解析一个公共域名(如
getaddrinfo("dns.google", "53", &hints, &result)),超时设为 2s;失败则大概率 DNS 不通 - 进一步可尝试用
WSASocket+connect连接8.8.8.8:53(UDP 也可,但需处理 ICMP port unreachable) - 注意:不要用阻塞 socket 做全链路探测,容易卡主线程;建议用完成端口或
std::thread+std::future包裹
这个组合虽不完美,但比单靠 InternetGetConnectedState 少踩 70% 的坑。
真正的难点不在 API 调用本身,而在于「系统认为有网」和「你的应用能发请求」之间存在多层中间件(NCSI、组策略、WFP 筛选器、第三方安全软件 Hook),这些都不可见。所以最稳的做法是:首次获取状态后缓存 10–30 秒,后续请求失败时再触发重检,而不是每次发包前都查一遍。


















