Visual C++ 編程實現Soft AP (HostedNetwork / 承載網絡) 功能


從Windows 7開始,微軟在操作系統中加入的Soft AP功能,使用戶能夠通過無線網卡,開啟虛擬AP,從而實現網絡共享。Soft AP又稱HostedNetwork(承載網絡),在Windows SDK中,提供了相應的API,以WlanHostedNetwork***開頭的一系列函數。

 

要編碼實現Soft AP,首先需要添加相應的頭文件及lib庫

1 #include <wlanapi.h>
2 #include <iphlpapi.h>
3 #include <winsock2.h>
4 #pragma comment(lib, "ws2_32.lib")
5 #pragma comment(lib, "Wlanapi.lib")
6 #pragma comment(lib, "IPHLPAPI.lib"

其中,wlanapi.h是無線網絡API的聲明文件,函數名一般以Wlan開頭。iphlpapi.h用於調用GetAdapterInfo函數,獲取網絡虛擬接口信息。

 

和winsock套接字編程類似,Wlan庫使用前需獲得句柄,並進行版本協商,只不過都在WlanOpenHandle實現了。使用完句柄后,調用WlanCloseHandle關閉以釋放資源。

WlanOpenHandle原形如下:

1 DWORD WINAPI WlanOpenHandle(
2   _In_        DWORD dwClientVersion,
3   _Reserved_  PVOID pReserved,
4   _Out_       PDWORD pdwNegotiatedVersion,
5   _Out_       PHANDLE phClientHandle
6 );

dwClientVersion指定程序期望使用的Wlan版本,使用宏WLAN_API_VERSION代替。從vista開始,版本號為2,xp系統為1。協商后的版本通過參數pdwNegotiatedVersion返回,通過檢查主版本號來驗證(如下代碼所示)。句柄通過phClient返回。

 

 1     DWORD dwError = 0;
 2     DWORD dwServiceVersion = 0;
 3     HANDLE hClient = NULL;
 4 
 5     if (ERROR_SUCCESS != (dwError = WlanOpenHandle(
 6         WLAN_API_VERSION,   
 7         NULL,               // reserved
 8         &dwServiceVersion,
 9         &hClient
10         )))
11     {
12         return -1;
13     }
14 
15     // check service version
16     if (WLAN_API_VERSION_MAJOR(dwServiceVersion) < WLAN_API_VERSION_MAJOR(WLAN_API_VERSION_2_0))
17     {
18         WlanCloseHandle(hClient, NULL);
19     }

 

  

 啟動承載網絡前,需要將模式配置為allow狀態,並設置SSID和密碼。可以調用WlanHostedNetworkSetProperty進行設置,WlanHostedNetworkSetProperty原型如下:

1 DWORD WINAPI WlanHostedNetworkSetProperty(
2   _In_        HANDLE hClientHandle,
3   _In_        WLAN_HOSTED_NETWORK_OPCODE OpCode,
4   _In_        DWORD dwDataSize,
5   _In_        PVOID pvData,
6   _Out_opt_   PWLAN_HOSTED_NETWORK_REASON pFailReason,
7   _Reserved_  PVOID pvReserved
8 );

其中hClientHandle是我們之前調用WlanOpenHnadle獲得的句柄;dwDataSize指定了pvData緩沖區的大小,而pvData指向的變量類型取決與OpCode的取值。OpCode為WLAN_HOSTED_NETWORK_OPCODE枚舉,如果指定為wlan_hosted_network_opcode_enable,那么pvData傳入一個BOOL型的變量指針,用於指示承載網絡模式為允許還是禁止(allow/disallow);如果OpCode為wlan_hosted_network_opcode_connection_settings,那么pvData指向WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS結構體,指定承載網絡的SSID和最大連接數目(peer count).

 

示例代碼:

 1     // 設置承載網絡模式為允許
 2     BOOL bIsAllow = TRUE;
 3     WLAN_HOSTED_NETWORK_REASON dwFailedReason;
 4     DWORD dwReturnValue = WlanHostedNetworkSetProperty(hWlanClient, 
 5         wlan_hosted_network_opcode_enable, 
 6         sizeof(BOOL), 
 7         &bIsAllow, 
 8         &dwFailedReason, 
 9         NULL);
10 
11     if(ERROR_SUCCESS != dwReturnValue)
12     {
13         return -1;
14     }
15 
16 
17 
18 
19     // 設置承載網絡的SSID和最大連接數
20     WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS wlanConnectionSetting;
21     memset(&wlanConnectionSetting, 0, sizeof(WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS));
22 
23     // WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS中的SSID字段必須為ANSI類型,因此如果程序使用的是Unicode,則需要做轉換。
24 #ifdef _UNICODE
25     WideCharToMultiByte(CP_ACP,
26         0,
27         strSSID.GetBuffer(0),   // 保存SSID的CString類型
28         strSSID.GetLength(),    // SSID字符串的長度
29         (LPSTR)wlanConnectionSetting.hostedNetworkSSID.ucSSID,
30         32,
31         NULL,
32         NULL);
33 #else
34     memcpy(wlanConnectionSetting.hostedNetworkSSID.ucSSID, strSSID.GetBuffer(0), strlen(strSSID.GetBuffer(0)));
35 #endif   
36 
37     wlanConnectionSetting.hostedNetworkSSID.uSSIDLength = strlen((const char*)wlanConnectionSetting.hostedNetworkSSID.ucSSID);
38     wlanConnectionSetting.dwMaxNumberOfPeers = 100;    
39 
40     dwReturnValue = WlanHostedNetworkSetProperty(m_hWlanClient, 
41         wlan_hosted_network_opcode_connection_settings, 
42         sizeof(WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS), 
43         &wlanConnectionSetting,
44         &dwFailedReason,
45         NULL);
46     if(ERROR_SUCCESS != dwReturnValue)
47     {
48         return -1;
49     }

 

 

調用WlanHostedNetworkSetSecondaryKey函數,設置承載網絡的連接密碼,函數原型如下:

1 DWORD WINAPI WlanHostedNetworkSetSecondaryKey(
2   _In_        HANDLE hClientHandle,
3   _In_        DWORD dwKeyLength,
4   _In_        PUCHAR pucKeyData,
5   _In_        BOOL bIsPassPhrase,
6   _In_        BOOL bPersistent,
7   _Out_opt_   PWLAN_HOSTED_NETWORK_REASON pFailReason,
8   _Reserved_  PVOID pvReserved
9 );

hClientHandle是我們之前調用WlanOpenHnadle獲得的句柄;

bIsPassPhrase表明傳入pucKeyData的密碼是否為口令格式,如果是口令格式,則是8-63位的ASCII字符串,該參數設置為TRUE;如果為16進制的binary,參數設置為FALSE;

dwKeyLength是密碼緩沖區的長度,密碼為口令格式時,必須包括結尾的'\0'

pucKeyData如果字符串,則必須為ANSI類型,因此如果IDE環境將字符串配置為UNICODE,需要做轉換,可使用WideCharToMultiByte,或者T2A,W2A宏。

bPersistent用來指示密碼是否是持久的。如果不是,那么該密碼只在本次啟動有效;否則下次啟動Soft AP依然使用本次設置的密碼。

 

示例代碼:

 1     UCHAR keyBuf[100] = {0};
 2 #ifdef _UNICODE
 3     WideCharToMultiByte(CP_ACP,
 4         0,
 5         strSecondaryKey.GetBuffer(0),
 6         strSecondaryKey.GetLength(),
 7         (LPSTR)keyBuf,
 8         100,
 9         NULL,
10         NULL);
11 #else
12     memcpy(keyBuf, strSecondaryKey.GetBuffer(0), strlen(strSecondaryKey.GetBuffer(0)));
13 #endif
14     dwReturnValue = WlanHostedNetworkSetSecondaryKey(m_hWlanClient,
15         strlen((const char*)keyBuf) + 1,
16         keyBuf,
17         TRUE,
18         FALSE,
19         &dwFailedReason,
20         NULL);
21     if(ERROR_SUCCESS != dwReturnValue)
22     {
23         return -1;
24     }

 

 

啟動或者停止Soft AP,需要用到如下四個函數:

 1 DWORD WINAPI WlanHostedNetworkStartUsing(
 2   _In_        HANDLE hClientHandle,
 3   _Out_opt_   PWLAN_HOSTED_NETWORK_REASON pFailReason,
 4   _Reserved_  PVOID pvReserved
 5 );
 6 
 7 
 8 DWORD WINAPI WlanHostedNetworkStopUsing(
 9   _In_        HANDLE hClientHandle,
10   _Out_opt_   PWLAN_HOSTED_NETWORK_REASON pFailReason,
11   _Reserved_  PVOID pvReserved
12 );
13 
14 DWORD WINAPI WlanHostedNetworkForceStart(
15   _In_        HANDLE hClientHandle,
16   _Out_opt_   PWLAN_HOSTED_NETWORK_REASON pFailReason,
17   _Reserved_  PVOID pvReserved
18 );
19 
20 DWORD WINAPI WlanHostedNetworkForceStop(
21   _In_        HANDLE hClientHandle,
22   _Out_opt_   PWLAN_HOSTED_NETWORK_REASON pFailReason,
23   _Reserved_  PVOID pvReserved
24 );

參數的含義很直觀,這里不再做更多地解釋。值得注意的是,如果用StartUsing或者StopUsing版本的函數時,如果有客戶端連接到了AP,調用WlanHostedNetworkStopUsing並不能立即停止Soft AP,而要等到客戶端主動斷開連接后,Soft AP才會停止。如果調用帶Force的函數版本,則會強制停止Soft AP,不管是否有客戶端正在連接到該AP上。當然,調用帶Force的函數版本需要程序以管理員方式啟動。

示例代碼:

 1     dwReturnValue = WlanHostedNetworkStartUsing(m_hWlanClient, &dwFailedReason, NULL);    
 2     if(ERROR_SUCCESS != dwReturnValue)
 3     {
 4         if (wlan_hosted_network_reason_interface_unavailable == dwFailedReason)
 5         {
 6             return 0;
 7         }
 8         return -1;
 9     }
10 
11     dwReturnValue = WlanHostedNetworkStopUsing(m_hWlanClient, &dwFailedReason, NULL);
12     if (ERROR_SUCCESS != dwReturnValue)
13     {
14         return -1;
15     }

 

 

啟動Soft AP后,綁定Ip需要一定的時間,一般為2-3秒。Ip地址一般為192.168.173.1(也有可能是192.168.137.1). 

 

 

調試程序時,可使用命令行方式使用Soft AP(管理員方式打開cmd):

查看當前承載網絡狀態 - netsh wlan show hostednetwork 

配置承載網絡屬性,如SSID,密碼等 - netsh wlan set hostednetwork ssid=***** key=***** mode=allow|disallow  (星號部分為ascii字符,key必須在8-63個字符之間)

啟動承載網絡 - netsh wlan start hostednetwork

關閉承載網絡 - netsh wlan stop hostednetwork

 

 

如果本文對你有幫助,可以考慮捐贈以支持作者。

比特幣地址:   1NPXhyv9W1tcqQc8iiSgx4YyPYbfoLSVzf

萊特幣地址:   LSXEAZt67sdpBjZ7yhvTpPUjy6hZKivYph


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM