在Win32 API
函數中有一組用于實現遠程連接服務RAS
的函數,利用這些函數通過編程可以實現建立和Internet
的撥號連接,并可獲得Internet 分配給主機的動態IP 地址。
一、建立撥號連接API
建立撥號連接是利用函數RasDial()
實現的,該函數調用后立即返回,若成功返回0 值,否則返回非0
值。在撥號連接過程中,回調函數接收連接的狀態信息及發生的錯誤代碼?;卣{函數的原形如下:VOID
WINAPI RasDialFunc(UINT unMsg,RASCONNSTATE rasconnstate,DWORD dwError)
由于在調用RasDialFunc
函數時,連接操作被掛起,因此,應用程序應盡快處理發生的事件并返回??梢栽赗asDialFunc
函數中調用PostMessage 函數,將事件通知消息送給窗口函數來處理。
RASDIALPARAMS 結構定義如下:
DWORD dwSize 結構變量的大小。
TCHAR szEntryName[RAS_MaxEntryName +1] 撥號網絡中建立的連接名。
TCHAR szPhoneNumber[RAS_MaxPhoneNumber +1] 電話號碼,若采用szEntryName
中定義的號碼,置為NULL 值。
TCHAR szCallbackNumber[RAS_MaxCallbackNumber +1] 回撥號碼,不用時置為NULL。
TCHAR szUserName[UNLEN +1] 用戶標識。
TCHAR szPassword[PWLEN +1] 用戶口令。
TCHAR szDomain[DNLEN +1] 用戶權限驗證域,若為NULL 采用RAS
服務器所在的域進行驗證,若為‘*’采用szEntryName
中定義的域進行驗證。
RASCONNSTATE
枚舉型結構,包含撥號連接過程中各種可能狀態的定義。
函數RasHangUp()
用來終止撥號連接,因程序需要一定的時間來結束連接,應用程序調用該函數后不能馬上退出,需等待3
秒后才能退出。
二、獲取動態IP 地址API
在VC 中是通過調用函數RasGetProjectionInfo() 來獲取IP 地址的。
函數調用成功時返回0 值,此時在RASPPPIP 結構變量中的szIpAddress
就是動態IP 地址。
三、程序實現
程序是在Win 95 環境下,用VC ++5.0
編寫,并編譯運行通過。完整的源程序清單如下:
// ---?。?br>
//file name ras.c
// ---?。?br>
#include < windows.h >
#include < winuser.h >
#include < string.h >
#include < ras.h >
#include < raserror.h >
#include "resource.h"
// 函數原形
LRESULT CALLBACK DialogProc(HWND hDlg,
UINT message, WPARAM wParam, LPARAM lParam);
void ShowMsg(HWND hwnd,char *msg);
LRESULT MsgDialDlgEvent(HWND hdlg,
UINT uMessage, WPARAM wparam, LPARAM lparam);
VOID WINAPI RasDialFunc
( UINT unMsg, RASCONNSTATE rasconnstate,
DWORD dwError );
BOOL StartCon( HWND hWnd,char
*szUser,char *szPassword );
UINT GetRasConnState( RASCONNSTATE rasconn );
// 全局變量
HRASCONN hCon; //RAS 連接句柄
HWND hWin;
HINSTANCE hInst;
// ---?。?br>
//windows 入口函數
// ---?。?br>
int PASCAL WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,LPSTR lpszCmdLine,
int nCmdShow )
{
hInst=hInstance;
if ( DialogBox(hInstance,"RAS_DLG",NULL,
(DLGPROC)DialogProc) == -1 )
MessageBox(NULL,"建立對話框失??!",
"TITLE",MB_OK);
return 0;
}
// -----------------
// 對話框窗口函數
// -----------------
LRESULT CALLBACK DialogProc(HWND hDlg,
UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
hWin=hDlg;
hCon=NULL;
return (TRUE);
case WM_RASDIALEVENT:
MsgDialDlgEvent(hDlg,message,wParam,lParam);
return (TRUE);
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
StartCon( hDlg,"ljx@public.smptt.fj.cn",
"abbcd");
break;
case IDCANCEL:
if ( hCon != NULL )
{
RasHangUp(hCon);
Sleep(3000);
}
EndDialog(hDlg,TRUE);
break;
}
break;
}
return (FALSE);
}
// ****************
// 在列表框中顯示信息
// ****************
void ShowMsg(HWND hwnd,char *msg)
{
int lnum;
SendDlgItemMessage(hwnd,IDC_MSG,
LB_ADD ?STRING,0,(long)msg );
lnum=SendDlgItemMessage(hwnd,IDC_MSG,
LB_GETCOUNT, 0,0);
SendDlgItemMessage(hwnd,IDC_MSG,LB_SET ?
CURSEL,lnum -1,0);
return;
}
// -----------------
// BOOL StartCon( HWND hWnd )
// 建立撥號連接, 成功TRUE else FALSE
// szUser 和szPassword 分別為
Internet 的用戶名和口令
// -----------------
BOOL StartCon
( HWND hWnd,char *szUser,char *szPassword )
{
RASDIALPARAMS rdParams;
DWORD dwRet;
char szBuf[300];
// 初始化變量
rdParams.dwSize = sizeof(RASDIALPARAMS);
lstrcpy(rdParams.szEntryName, "internet");
rdParams.szPhoneNumber[0] = '\0';
rdParams.szCallbackNumber[0] = '*';
rdParams.szCallbackNumber[0] = '\0';
strcpy(rdParams.szUserName,szUser);
strcpy(rdParams.szPassword,szPassword);
rdParams.szDomain[0] = '\0';
hCon=NULL;
// 以下開始異步撥叫網絡
dwRet = RasDial( NULL, NULL, &rdParams, 0L,
(RASDIALFUNC) RasDialFunc, &hCon );
if ( dwRet )
{
if ( RasGetErrorString( (UINT)dwRet,
(LPSTR)szBuf, 256 ) != 0 )
wsprintf( (LPSTR)szBuf,
“Undefined RAS Dial Error ( %ld).", dwRet );
ShowMsg(hWnd,szBuf);
return FALSE;
}
return TRUE;
}
// ---------------
// RasDial 異步處理的回調函數
// unMsg?。l生的RAS 事件
// rasconnstate -連接進入的狀態
// dwError ?。l生的錯誤代碼
// ---------------
VOID WINAPI RasDialFunc
( UINT unMsg, RASCONNSTATE rasconnstate,
DWORD dwError )
{
PostMessage(hWin,
WM_RASDIALEVENT,
(WPARAM) rasconnstate,
(LPARAM) dwError );
}
// ----------------
// RasDial() 返回的事件信息由該函數處理
// ----------------
LRESULT MsgDialDlgEvent(HWND hdlg, UINT uMessage,
WPARAM wparam, LPARAM lparam)
{
RASPPPIP rip;
DWORD ll,ret;
int num;
char szMessage[256];
LoadString(hInst,GetRasConnState
( (RASCONNSTATE) wparam ), szMessage, 64 );
ShowMsg(hdlg,szMessage);
if ( lparam ) // 發生錯誤
{
if ( RasGetErrorString
( (UINT)lparam, szMessage, 256 ) != 0 )
wsprintf( (LPSTR)szMessage,
“出錯Undefined RAS Dial Error." );
ShowMsg(hdlg,szMessage);
return TRUE;
}
else if ( RASCS_DONE &wparam ) // 連接成功
{
// 取動態分配的IP 地址
ShowMsg(hdlg,"連接成功");
rip.dwSize=sizeof(RASPPPIP);
if((ret=RasGetProjectionInfo(hCon,RASP_PppIp,
(LPVOID) &rip,(LPDWORD) &ll )) != 0 )
{
ShowMsg(hdlg,"取IP 地址失敗");
}
else
ShowMsg(hdlg,rip.szIpAddress);
}
return TRUE;
}
// ----------------
// 根據連接狀態
取字符串資源中對應的標號
// ----------------
UINT GetRasConnState( RASCONNSTATE rasconn )
{
switch( rasconn )
{
case RASCS_OpenPort:
return IDS_OPENPORT;
case RASCS_PortOpened:
return IDS_PORTOPENED;
case RASCS_ConnectDevice:
return IDS_CONNECTDEVICE;
case RASCS_DeviceConnected:
return IDS_DEVICECONNECTED;
case RASCS_AllDevicesConnected:
return IDS_ALLDEVICESCONNECTED;
case RASCS_Authenticate:
return IDS_AUTHENTICATE;
case RASCS_AuthNotify:
return IDS_AUTHNOTIFY;
case RASCS_AuthRetry:
return IDS_AUTHRETRY;
case RASCS_AuthCallback:
return IDS_AUTHCALLBACK;
case RASCS_AuthChangePassword:
return IDS_AUTHCHANGEPASSWORD;
case RASCS_AuthProject:
return IDS_AUTHPROJECT;
case RASCS_AuthLinkSpeed:
return IDS_AUTHLINKSPEED;
case RASCS_AuthAck:
return IDS_AUTHACK;
case RASCS_ReAuthenticate:
return IDS_REAUTHENTICATE;
case RASCS_Authenticated:
return IDS_AUTHENTICATED;
case RASCS_PrepareForCallback:
return IDS_PREPAREFORCALLBACK;
case RASCS_WaitForModemReset:
return IDS_WAITFORMODEMRESET;
case RASCS_WaitForCallback:
return IDS_WAITFORCALLBACK;
case RASCS_Interactive:
return IDS_INTERACTIVE;
case RASCS_RetryAuthentication:
return IDS_RETRYAUTHENTICATION;
case RASCS_CallbackSetByCaller:
return IDS_CALLBACKSETBYCALLER;
case RASCS_PasswordExpired:
return IDS_PASSWORDEXPIRED;
case RASCS_Connected:
return IDS_CONNECTED;
case RASCS_Disconnected:
return IDS_DISCONNECTED;
default:
return IDS_UNDEFINED_ERROR;
}
}