在linux下获取当前连接的信息很是轻松的,但是在windows下相对比较复杂,虽然可以考虑使用cmd命令获取网卡的信息并分析出当前连接的SSID,但是对于网络环境比较复杂的情况下其实我们同样可以使用Native wifi API获取目前的连接信息。
原理是通过打开网卡设备获取其连接信息,并提供给我们的程序使用。在此对网上的一些资料做了一些整理和总结。
一、首先是我们所需要的结构体:
typedef struct _WLAN_AVAILABLE_NETWORK {
WCHAR strProfileName[WLAN_MAX_NAME_LENGTH];
DOT11_SSID dot11Ssid;
DOT11_BSS_TYPE dot11BssType;
ULONG uNumberOfBssids;
BOOL bNetworkConnectable;
WLAN_REASON_CODE wlanNotConnectableReason;
ULONG uNumberOfPhyTypes;
DOT11_PHY_TYPE dot11PhyTypes[WLAN_MAX_PHY_TYPE_NUMBER];
BOOL bMorePhyTypes;
WLAN_SIGNAL_QUALITY wlanSignalQuality;
BOOL bSecurityEnabled;
DOT11_AUTH_ALGORITHM dot11DefaultAuthAlgorithm;
DOT11_CIPHER_ALGORITHM dot11DefaultCipherAlgorithm;
DWORD dwFlags;
DWORD dwReserved;
} WLAN_AVAILABLE_NETWORK, *PWLAN_AVAILABLE_NETWORK;
具体参考微软的API描述清晰明了:
Members:
strProfileName
Contains the profile name associated with the network. If the network does not have a profile, this member will be empty. If multiple profiles are associated with the network, there will be multiple entries with the same SSID in the visible network list. Profile names are case-sensitive. This string must be NULL-terminated.
dot11Ssid
A DOT11_SSID structure that contains the SSID of the visible wireless network.
dot11BssType
A DOT11_BSS_TYPE value that specifies whether the network is infrastructure or ad hoc.
uNumberOfBssids
Indicates the number of BSSIDs in the network.
Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: uNumberofBssids is at most 1, regardless of the number of access points broadcasting the SSID.
bNetworkConnectable
Indicates whether the network is connectable or not. If set to TRUE, the network is connectable, otherwise the network cannot be connected to.
wlanNotConnectableReason
A WLAN_REASON_CODE value that indicates why a network cannot be connected to. This member is only valid whenbNetworkConnectable is FALSE.
uNumberOfPhyTypes
The number of PHY types supported on available networks. The maximum value of uNumberOfPhyTypes is WLAN_MAX_PHY_TYPE_NUMBER, which has a value of 8. If more than WLAN_MAX_PHY_TYPE_NUMBER PHY types are supported, bMorePhyTypes must be set to TRUE.
dot11PhyTypes
Contains an array of DOT11_PHY_TYPE values that represent the PHY types supported by the available networks. When uNumberOfPhyTypes is greater than WLAN_MAX_PHY_TYPE_NUMBER, this array contains only the first WLAN_MAX_PHY_TYPE_NUMBER PHY types.
bMorePhyTypes
Specifies if there are more than WLAN_MAX_PHY_TYPE_NUMBER PHY types supported.
When this member is set to TRUE, an application must call WlanGetNetworkBssList to get the complete list of PHY types. The returned WLAN_BSS_LIST structure has an array of WLAN_BSS_ENTRY structures. The uPhyId member of the WLAN_BSS_ENTRYstructure contains the PHY type for an entry.
wlanSignalQuality
A percentage value that represents the signal quality of the network. WLAN_SIGNAL_QUALITY is of type ULONG. This member contains a value between 0 and 100. A value of 0 implies an actual RSSI signal strength of -100 dbm. A value of 100 implies an actual RSSI signal strength of -50 dbm. You can calculate the RSSI signal strength value for wlanSignalQuality values between 1 and 99 using linear interpolation.
bSecurityEnabled
Indicates whether security is enabled on the network. A value of TRUE indicates that security is enabled, otherwise it is not.
dot11DefaultAuthAlgorithm
A DOT11_AUTH_ALGORITHM value that indicates the default authentication algorithm used to join this network for the first time.
dot11DefaultCipherAlgorithm
A DOT11_CIPHER_ALGORITHM value that indicates the default cipher algorithm to be used when joining this network.
dwFlags
Contains various flags for the network.
Value Meaning WLAN_AVAILABLE_NETWORK_CONNECTED
This network is currently connected. WLAN_AVAILABLE_NETWORK_HAS_PROFILE
There is a profile for this network.
dwReserved
Reserved for future use. Must be set to NULL.
二、打开Wlan设备,获取设备资源句柄:
DWORD WINAPI
WlanOpenHandle(
__in DWORD dwClientVersion,
__reserved PVOID pReserved,
__out PDWORD pdwNegotiatedVersion,
__out PHANDLE phClientHandle
);
其中:
dwClientVersion:对于windows XP 的SP2或者SP3版本,取值为 1
对于Windows Vista 和WindowsServer 2008 取值为 2
pReserved:取值为NULL
pdwNegotiatedVersion :返回参数,返回当前使用的version,比如你在xpsp2下它就返回1。
phClientHandle :Specifies a handle for the client to use in this session. This handle is used by other functions throughout the session(即wifi设备的句柄,在整个扫描或者连接wifi过程中都会被用到)。
Return value:成功返回ERROR_SUCCESS,错误会返回错误代码。
且在MSDN上:
WlanOpenHandle will return an error message if the Wireless Zero Configuration (WZC) service has not been started or if the WZC service is not responsive.(必须启动WZC服务,不然WlanOpenHandle 返回失败)。
三、通过WlanEnumInterfaces列出无线网卡设备
DWORD WINAPI
WlanEnumInterfaces(
__in HANDLE hClientHandle,
__reserved PVOID pReserved,
__deref_out PWLAN_INTERFACE_INFO_LIST *ppInterfaceList
);
hClientHandle :通过WlanOpenHandle获取的wifi设备资源的句柄(The client's session handle, obtained by a previous call to the WlanOpenHandle function.)。
pReserved :NULL
ppInterfaceList :指针结构体,它是存储wireless LANinterfaces 的一个结构体。Pointer to a WLAN_INTERFACE_INFO_LIST structure that contains the list of NIC interfaces.(网卡接口信息列表结构的指针,NIC:Network Interface Card,也就是网络适配器/网卡),This function will allocate memory for the list of returned interfaces. The caller is responsible for freeing this memory using the WlanFreeMemory function(意思就是你传一个空指针的地址进去就行了,系统自动分配,你记得用完后用WlanFreeMemory释放)。
Return value:成功返回ERROR_SUCCESS,错误会返回错误代码。
对于WLAN_INTERFACE_INFO_LIST:
typedef struct _WLAN_INTERFACE_INFO_LIST {
DWORD dwNumberOfItems;
DWORD dwIndex;
#if ...
WLAN_INTERFACE_INFO *InterfaceInfo[];
#else
WLAN_INTERFACE_INFO InterfaceInfo[1];
#endif
} WLAN_INTERFACE_INFO_LIST, *PWLAN_INTERFACE_INFO_LIST;
dwNumberOfItems:
Contains the number of items in the InterfaceInfo member(InterfaceInfo[ ] 中包含的单元的个数)
dwIndex:
The index of the current item. The index of the first item is 0. dwIndex must be less than dwNumberOfItems.
This member is not used by the wireless service. Applications can use this member when processing individual interfaces in theWLAN_INTERFACE_INFO_LIST structure. When an application passes this structure from one function to another, it can set the value of dwIndex to the index of the item currently being processed. This can help an application maintain state.
dwIndex should always be initialized before use.
0到dwNumberOfItems-1, 一般用于在 WLAN_INTERFACE_INFO_LIST 作为参数传递时的一个传递偏移量。这个参数在用之前必须要进行初始化
InterfaceInfo[ ]:
An array of WLAN_INTERFACE_INFO structures containing interface information.(包含LAN_INTERFACE_INFO 结构体的阵列,用于记录接口信息)。其描述如下:
typedef struct _WLAN_INTERFACE_INFO {
GUID InterfaceGuid;
WCHAR strInterfaceDescription[WLAN_MAX_NAME_LENGTH];
WLAN_INTERFACE_STATE isState;
} WLAN_INTERFACE_INFO, *PWLAN_INTERFACE_INFO;
InterfaceGuid:
Contains the GUID of the interface.(接口的GUID,GUID:Globally Unique Identifier(全球唯一标识符),据称是根椐时间,网卡,机器名等结合算法生成的,所以唯一,所以调用者在某些函数中可以通过GUID来指定特定网卡)。
strInterfaceDescription:
Contains the description of the interface.(接口的描绘信息,打开设备管理器-无线网卡属性可以看到描述)
isState:
Contains a WLAN_INTERFACE_STATE value that indicates the current state of the interface.
Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: Only the wlan_interface_state_connected, wlan_interface_state_disconnected, and wlan_interface_state_authenticating values are supported.(包含一个 WLAN_INTERFACE_STATE值,标示这个NIC接口的当前状态)。其详细如下:
typedef enum _WLAN_INTERFACE_STATE {
wlan_interface_state_not_ready,
wlan_interface_state_connected,
wlan_interface_state_ad_hoc_network_formed,
wlan_interface_state_disconnecting,
wlan_interface_state_disconnected,
wlan_interface_state_associating,
wlan_interface_state_discovering,
wlan_interface_state_authenticating
} WLAN_INTERFACE_STATE, *PWLAN_INTERFACE_STATE;
WirelessLAN API for Windows XP SP2:
Only the wlan_interface_state_connected, wlan_interface_state_disconnected, and wlan_interface_state_authenticating values are supported.(xpsp2下仅支持已连接,已断开,生效中这三种状态)。
四、通过WlanGetAvailableNetworkList获得有效的无线网络信息
DWORD WlanGetAvailableNetworkList(
HANDLE hClientHandle,
const GUID *pInterfaceGuid,
DWORD dwFlags,
PVOID pReserved,
PWLAN_AVAILABLE_NETWORK_LIST *ppAvailableNetworkList
);
hClientHandle:
The client's session handle, obtained by a previous call to the WlanOpenHandle function.(WlanOpenHandle返回的那个客户端句柄)
pInterfaceGuid:
The GUID of the interface to be queried.(上面 WLAN_INTERFACE_INFO 的GUID,也就是网卡的GUID)
dwFlags:
Controls the type of networks returned in the list(控制ppAvailableNetworkList中获得的网络类型),其值为0,1,2,3(1和2组合)四种选择
1:Include all ad-hoc network profiles in the available network list, including profiles that are not visible.(ad-hoc network :即点对点方式的无线网络,包括profiles name(配置文件名称)不可见(获得profiles name字符为空)的所有点对对无线网络)
2:Include all hidden network profiles in the available network list, including profiles that are not visible.(包括profiles name(配置文件名称)不可见(获得profiles name字符为空)的所有隐藏网络配置)
3:前二者的组合
ppAvailableNetworkList:Pointer to a WLAN_AVAILABLE_NETWORK_LIST to receive the returned list of visible networks.(无线网络列表)This function will allocate memory for the list of returned interfaces. The caller is responsible for freeing this memory using the WlanFreeMemory function(传一个空指针的地址进去就行了,系统自动分配,调用者负责用WlanFreeMemory释放)
这个结构和WLAN_INTERFACE_INFO_LIST 相仿.
简单demo
int GetInfo()
{
int id = 0;
HANDLE ClientHandle;
DWORD nv, i, j;
PWLAN_INTERFACE_INFO_LIST ilist;
PWLAN_AVAILABLE_NETWORK_LIST nlist;
static char ssid[36];
setlocale(LC_ALL, "chs");
if (WlanOpenHandle(1, 0, &nv, &ClientHandle) == 0)
{
if (WlanEnumInterfaces(ClientHandle, 0, &ilist) == 0)
{
for (i = 0; i < ilist->dwNumberOfItems; i++)
{
wprintf(L"网卡: %s\n\n", ilist->InterfaceInfo[i].strInterfaceDescription);
if (WlanGetAvailableNetworkList(ClientHandle, &ilist->InterfaceInfo[i].InterfaceGuid, 0, 0, &nlist) == 0)
{
for (j = 0; j < nlist->dwNumberOfItems; j++)
{
memcpy(ssid, nlist->Network[j].dot11Ssid.ucSSID, nlist->Network[j].dot11Ssid.uSSIDLength);
ssid[nlist->Network[j].dot11Ssid.uSSIDLength] = 0;
printf("%d. SSID: %-25s 信号强度: %5d\n", id++, ssid, nlist->Network[j].wlanSignalQuality);
//可继续获取BSSID
if (1)
{
PWLAN_BSS_LIST ppWlanBssList; //BSS网络列表
auto dwResult = WlanGetNetworkBssList(
ClientHandle,
&ilist->InterfaceInfo[i].InterfaceGuid,
&nlist->Network[j].dot11Ssid, nlist->Network[j].dot11BssType,
nlist->Network[j].bSecurityEnabled,
NULL, &ppWlanBssList);
if (ERROR_SUCCESS == dwResult)
{
for (int k = 0; k < ppWlanBssList->dwNumberOfItems; k++)
{
printf(" %3 MAC:");
printf("%02X:%02X:%02X:%02X:%02X:%02X",
ppWlanBssList->wlanBssEntries[k].dot11Bssid[0],
ppWlanBssList->wlanBssEntries[k].dot11Bssid[1],
ppWlanBssList->wlanBssEntries[k].dot11Bssid[2],
ppWlanBssList->wlanBssEntries[k].dot11Bssid[3],
ppWlanBssList->wlanBssEntries[k].dot11Bssid[4],
ppWlanBssList->wlanBssEntries[k].dot11Bssid[5]
);
printf("\n");
}
}
}
}
WlanFreeMemory(nlist);
}
}
WlanFreeMemory(ilist);
}
system("pause>nul");
WlanCloseHandle(ClientHandle, 0);
}
system("pause");
return true;
}
至此通过wlanapi获取无线网络信息基本完成,可以获取当前无线连接SSID,或进行下一步操作。
参考文章:Native wifi API使用_hgy413的专栏-CSDN博客_native wifi
Windows下无线局域网设备SSID和BSSID获取方法(C语言)_匿名用户_的博客-CSDN博客_无线网bssid和ssid