台式计算机 - 检测互联网连接类型

时间:2015-07-14 12:31:14

标签: networking connection

有没有办法检测我的电脑是否通过有线电视或移动网络连接到互联网?

我尝试分析跟踪路由输出,但意识到需要一个非常大且最新的数据库来检测数据包所采用的网络类型。

这两种不同类型的网络是否有一些易于检测的不同属性?

1 个答案:

答案 0 :(得分:0)

您可以使用NetworkListManager APIs查找网络是否已连接到互联网。下面的示例同时执行此操作并检查网络是否空闲。您只需删除与费用相关的代码:

HRESULT GetFreeInternetInterface(_Out_ GUID* pInterfaceGuid)
{
    bool fCoInitialized = false;
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if (SUCCEEDED(hr))
    {
        fCoInitialized = true;
        CComPtr<INetworkListManager> pNetworkListManager; 
        hr = pNetworkListManager.CoCreateInstance(__uuidof(NetworkListManager));
        if (SUCCEEDED(hr))
        {
            CComPtr<IEnumNetworkConnections> pNetworkConnections;
            hr = pNetworkListManager->GetNetworkConnections(&pNetworkConnections);

            bool fFound = false;
            while (SUCCEEDED(hr))
            {
                CComPtr<INetworkConnection> pNetworkConnection;
                hr = pNetworkConnections->Next(1, &pNetworkConnection, nullptr);
                if (hr == S_OK)
                {
                    CComPtr<INetworkConnectionCost> pNetworkConnectionCost;
                    hr = pNetworkConnection.QueryInterface(&pNetworkConnectionCost);

                    if (SUCCEEDED(hr))
                    {
                        NLM_CONNECTIVITY nlmConnectivity = NLM_CONNECTIVITY_DISCONNECTED;
                        DWORD dwCost = NLM_CONNECTION_COST_UNKNOWN;
                        if (SUCCEEDED(pNetworkConnection->GetConnectivity(&nlmConnectivity)) &&
                            (nlmConnectivity & (NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET)) != 0 &&
                            SUCCEEDED(pNetworkConnectionCost->GetCost(&dwCost)) &&
                            dwCost == NLM_CONNECTION_COST_UNRESTRICTED &&
                            SUCCEEDED(pNetworkConnection->GetAdapterId(pInterfaceGuid)))
                        {
                            fFound = true;
                            break;
                        }
                    }
                }
                else hr = E_NOINTERFACE;
            }

            if (SUCCEEDED(hr) && !fFound)
                hr = E_NOINTERFACE;
        }
    }
    if (fCoInitialized) CoUninitialize();
    return hr;
}

获得接口GUID和IP Helper APIs以获取接口类型。以下是我查找非蜂窝网络的一些代码。您可以将其修改并进行修改以满足您的需求:

BOOL GetAdapterAddresses(
    _Out_ PIP_ADAPTER_ADDRESSES * ppIAA
    )
{
    *ppIAA = NULL;

    DWORD len = 0;
    DWORD flags = GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER;
    if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &len) != ERROR_BUFFER_OVERFLOW)
        return FALSE;

    PIP_ADAPTER_ADDRESSES pIAA = (PIP_ADAPTER_ADDRESSES)LocalAlloc(LPTR, len);
    if (pIAA) {
        GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pIAA, &len);
        *ppIAA = pIAA;
        return TRUE;
    }
    return FALSE;
}

bool IsNonCellularIfType(
    _In_ IFTYPE IfType
    )
{
    return // Ignore Loopback and WWAN
        IfType != IF_TYPE_SOFTWARE_LOOPBACK &&
        IfType != IF_TYPE_WWANPP &&
        IfType != IF_TYPE_WWANPP2;
}

DWORD GetNonCellularIfIndex(
    )
{
    DWORD IfIndex = (DWORD)(-1);
    PIP_ADAPTER_ADDRESSES pIAA;
    if (GetAdapterAddresses(&pIAA)) {
        PIP_ADAPTER_ADDRESSES pIAAList = pIAA;
        while (pIAA) {
            // Look for Non-Cellular interface
            if (pIAA->OperStatus == IfOperStatusUp &&
                IsNonCellularIfType(pIAA->IfType)) {
                PIP_ADAPTER_UNICAST_ADDRESS_LH pUnicastAddr = pIAA->FirstUnicastAddress;
                // Look through all unicast addresses for valid IPv4 or IPv6 addresses
                while (pUnicastAddr) {
                    LPSOCKADDR pAddr = pUnicastAddr->Address.lpSockaddr;
                    if (pAddr->sa_family == AF_INET) {
                        if (!IN4_IS_ADDR_LINKLOCAL(&((SOCKADDR_IN *)pAddr)->sin_addr)) {
                            IfIndex = pIAA->IfIndex;
                            break;
                        }
                    }
                    else if (pAddr->sa_family == AF_INET6) {
                        if (!IN6_IS_ADDR_LINKLOCAL(&((SOCKADDR_IN6 *)pAddr)->sin6_addr)) {
                            IfIndex = pIAA->IfIndex;
                            break;
                        }
                    }
                    pUnicastAddr = pUnicastAddr->Next;
                }
                // No need to keep looking any more?
                if (IfIndex != (DWORD)(-1))
                    break; // while (pIAA)
            }
            pIAA = pIAA->Next;
        }

        LocalFree(pIAAList);
    }
    return IfIndex;
}