天天看點

WinCE6 建立APN撥接上網的經驗分享

    前天項目經理安排我做Wince6下面的APN撥接上網,任務很急,但我對APN一點概念都沒有,之前經理也收集了一些資料代碼,另外iPhone項目組的同僚也提供了設定APN的參數資訊(APN網絡名、帳号、手機号等)。由于以前做過Wince下普通的撥接上網,就在直接上面修改代碼。

    一邊看MSDN,一邊百度資料,還是有收獲,對APN有了一定了解:APN隻是在普通撥号的基礎上多了一些設定參數而已。然而就是這些參數,折磨了我兩天。

    要建立APN,首先要使用RasSetEntryProperties來修改撥接上網的屬性參數,函數原型如下:

DWORD RASAPI RasSetEntryProperties (

        LPWSTR lpszPhoneBook,  

        LPWSTR szEntry,

        LPRASENTRY lpEntry,

        DWORD dwEntrySize,

        LPBYTE lpb,

        DWORD dwSize

);

第一個參數直接設為NULL,第二個參數為撥接上網的名稱,比如‘寬帶連接配接’,如果名稱不存在,那麼系統自動建立一個新的連接配接,第三個參數是撥接上網的屬性,裡面内容繁多,不過隻需要設定部分内容即可,代碼如下:

RASENTRY g_objEntry = { 0 };

g_objEntry.dwSize = sizeof( RASENTRY );

_tcscpy( g_objEntry.szDeviceType, RASDT_Modem ); //裝置類型

_tcscpy( g_objEntry.szDeviceName, _T( "CDMAModem" )); //裝置名稱

_tcscpy( g_objEntry.szAreaCode, _T( "10" )); //區号

_tcscpy( g_objEntry.szLocalPhoneNumber, _T( "*99#" )); //手機号碼

g_objEntry.dwCountryCode = 86; //國家、地區代碼

g_objEntry.dwfNetProtocols = RASNP_Ip; //Negotiate the TCP/IP protocol.

g_objEntry.dwFramingProtocol = RASFP_Ppp; //Point-to-Point Protocol (PPP)

最關鍵的參數 g_objEntry.dwfOptions,因為項目裡面規定用使用PAP身份驗證協定,剛開始我就直接指派:

g_objEntry.dwfOptions = RASEO_ProhibitPAP;

沒想到就這一步錯大了,都怪我E文水準不高,最重要的是沒認真看MSDN的說明,下面是關于RASEO_ProhibitPAP的說明,各位看了就知道為什麼我錯了:

If this flag is set to 1, the use of the Password Authentication Protocol (PAP) authentication method is disabled. If the flag is set to zero (0), then the client can negotiate the use of the PAP authentication method with the server.

g_objEntry.dwfOptions最後指派為:

g_objEntry.dwfOptions =

  RASEO_ProhibitCHAP

| RASEO_ProhibitEAP       

| RASEO_ProhibitMsCHAP

| RASEO_ProhibitMsCHAP2     

| RASEO_UseCountryAndAreaCodes

| RASEO_SwCompression     

| RASEO_IpHeaderCompression;

注意,這裡要根據具體的情況而定,我們的項目指定要PAP。

下面繼續RasSetEntryProperties的第四個參數dwEntrySize,直接指派sizeof( RASENTRY )即可,第五個參數是序列槽參數以及APN指令,但是MSDN裡面沒有進一步說明資料是怎樣的格式,這樣導緻我花了大量的時間去百度,最終功夫不負有心人,終于找到了答案,下面是網友提供的資料定義:

#pragma pack(1)

typedef struct

{

unsigned short Reserved1; // 0x00, 通常為0x20   

unsigned short WaitForCreditCard; // 0x02 

unsigned short CancelTimeOut; // 0x04 

unsigned short Reserved2; // 0x06 

unsigned char Test1; // 0x08 

unsigned char Test2; // 0x09 

unsigned short Reserved3; // 0x0A 

unsigned int BaudRate; // 0x0C 

unsigned short Terminal; // 0x10, 通常為0, 1, 3, 7 

unsigned char DataBits; // 0x12 

unsigned char StopBits; // 0x13

unsigned char Parity; // 0x14 

unsigned char FlowControl; // 0x15 

TCHAR AtCmd[115]; // 0x16,

} sDevConfig;

#pragma pack()

我在使用中發現裡面有一個地方定義錯了,結構體成員Test1才是流控制,而FlowControl則固定為1。

至于AtCmd,APN指令,因為營運商以及手機卡的不同,内容可能不一樣,這裡我也把我所使用的格式發上來:

+CGDCONT=1,"IP","xxxx", xxxx代表APN網絡名,注意,我所使用的指令後面有一個逗号結尾。

後面的内容和普通撥接上網沒什麼差別,我就直接發代碼了:

RASDIALPARAM g_objDialParam = { 0 };

g_objDialParam.dwSize = sizeof( RASDIALPARAMS );

wcscpy( g_objDialParam.szEntryName, wszEntryName );

wcscpy( g_objDialParam.szUserName, _T( "*******" ));         //******代表使用者名

//采用異步的方式,通過視窗回調得到撥接上網的狀态

DWORD dwResult = RasDial( NULL, NULL, &g_objDialParam, 0xFFFFFFFF, hDlg, &g_hRasConn );

if ( 0 == dwResult )

{      

    WriteLogMsg( _T( "RasDial調用成功!" ));

}

else

{      

    WCHAR wszLog[256] = { 0 };

    _stprintf( wszLog, _T( "RasDial調用失敗!錯誤碼:%d" ), dwResult );

    WriteLogMsg( wszLog );

}

下面是處理撥号過程中的消息:

case WM_RASDIALEVENT:

{    

DWORD dwError = ( DWORD )lParam;    

RASCONNSTATE connState = ( RASCONNSTATE )wParam;

switch ( connState )    

{   

 case RASCS_OpenPort:                     

{       WriteLogMsg( _T( "RASCS_OpenPort..." ));       break;     }    

case RASCS_PortOpened:                  

 {       WriteLogMsg( _T( "RASCS_PortOpened." ));       break;     }   

case RASCS_ConnectDevice:             

 {       WriteLogMsg( _T( "RASCS_ConnectDevice..." ));       break;     }   

case RASCS_DeviceConnected:         

 {       WriteLogMsg( _T( "RASCS_DeviceConnected." ));       break;     }   

case RASCS_AllDevicesConnected:    

 {       WriteLogMsg( _T( "RASCS_AllDevicesConnected." ));       break;     }   

case RASCS_Authenticate:     

{       WriteLogMsg( _T( "RASCS_Authenticate..." ));       break;     }   

 case RASCS_Authenticated:     

{       WriteLogMsg( _T( "RASCS_Authenticated." ));       break;     }  

  case RASCS_Connected:    

 {       WriteLogMsg( _T( "RASCS_Connected." ));       break;     }  

case RASCS_Disconnected:   

  {       WriteLogMsg( _T( "RASCS_Disconnected." ));       break;     }

default:   

  {       WCHAR wszBuf[32] = { 0 };

       _stprintf( wszBuf, _T( "其他狀态: %d" ), connState );

       WriteLogMsg( wszBuf );       break;   

  }  

  }

if ( 0 != dwError )  

  {     

      WCHAR wszErrorMsg[128] = { 0 };

      _stprintf( wszErrorMsg, _T( "Dial Error: %d" ), dwError );

      WriteLogMsg( wszErrorMsg );   

 }

這裡可以下載下傳完整的撥号庫

.