首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Windows C++ 獲取當前應用使用的網絡類型:無直接 API,需特征分析

     編輯:程式設計綜合問答

Windows 無類似 Android ConnectivityManager.getActiveNetworkInfo() 的直接 API 獲取「當前應用使用的網絡類型(Wi-Fi/有線/蜂窩)」,需自行綜合多個介面特征判斷。

可行方案:綜合特征分析法

  1. 枚舉網卡信息:GetAdaptersAddresses() (優於 GetAdaptersInfo) 獲取所有網卡:IfType(IF_TYPE_IEEE80211=Wi-Fi, IF_TYPE_ETHERNET_CSMACD=有線)、OperStatus、Ipv4/IPv6 地址、FriendlyName(含 "Wi-Fi"/"Wireless" 關鍵字)。
  2. 獲取本機發送流量使用的源 IP:對目標服務器建立連接後,getsockname() 取得本地綁定的源 IP。
  3. 匹配源 IP 所屬網卡:將源 IP 與步驟 1 獲取的網卡單播地址對比,命中即為當前使用的網卡。
  4. 判斷網卡類型:根據該網卡的 IfType、名稱關鍵字、媒體連接狀態綜合判斷。

代碼框架

// 簡化邏輯,實際需處理多 IP、多網卡、VPN、虛擬網卡等邊界情況
DWORD GetCurrentNetworkType() {
    // 1. 連接目標服務器(或發送 UDP 包)獲取本地源 IP
    SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
    sockaddr_in dest = { AF_INET, htons(53), inet_addr("8.8.8.8") }; // Google DNS
    connect(s, (sockaddr*)&dest, sizeof(dest));
    sockaddr_in local; int len = sizeof(local);
    getsockname(s, (sockaddr*)&local, &len);
    closesocket(s);
    ULONG srcIp = local.sin_addr.S_un.S_addr;

    // 2. 枚舉網卡匹配
    ULONG bufSize = 15000; PIP_ADAPTER_ADDRESSES pAddr = (PIP_ADAPTER_ADDRESSES)malloc(bufSize);
    GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddr, &bufSize);
    for (PIP_ADAPTER_ADDRESSES p = pAddr; p; p = p->Next) {
        if (p->OperStatus != IfOperStatusUp) continue;
        for (PIP_ADAPTER_UNICAST_ADDRESS ua = p->FirstUnicastAddress; ua; ua = ua->Next) {
            if (ua->Address.lpSockaddr->sa_family == AF_INET) {
                auto ip = ((sockaddr_in*)ua->Address.lpSockaddr)->sin_addr.S_un.S_addr;
                if (ip == srcIp) {
                    // 3. 判斷類型
                    if (p->IfType == IF_TYPE_IEEE80211) return NET_WIFI;
                    if (p->IfType == IF_TYPE_ETHERNET_CSMACD) return NET_WIRED;
                    // 輔助:名稱含 "Wi-Fi"/"Wireless"/"802.11"
                    wstring name(p->FriendlyName);
                    if (name.find(L"Wi-Fi") != wstring::npos || name.find(L"Wireless") != wstring::npos)
                        return NET_WIFI;
                    return NET_UNKNOWN;
                }
            }
        }
    }
    free(pAddr);
    return NET_UNKNOWN;
}

難點與避坑

  • 多網卡同時活躍:路由表決定出口,源 IP 匹配法較準,但需處理多源 IP 情況。
  • VPN/虛擬網卡:IfType 可能為 IF_TYPE_TUNNEL、IF_TYPE_PPP,需識別並排除或標記為 VPN。
  • 權限:GetAdaptersAddresses 無需管理員權限,但部分 OID 查詢需提權。

結論:Windows 需自建「特征庫」(IfType、名稱關鍵字、媒體狀態)配合源 IP 匹配,無現成 API 一鍵獲取,屬系統級網絡編程進階課題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved