大家知道,在Netants、DownLoad Expert等軟件中都帶有定時撥號上網下載軟件的功能。而一般用戶的撥號上網,利用的是Windows的Remote
Access Service(RAS,遠程訪問服務)。下面介紹一下其在Visual C++下的實現。
Visual C++為我們提供了包含RAS API聲明的“ras.h″頭文件。要在程序中實現撥號上網功能,其大致過程如下:
1. 利用Modem撥號進行連接,應使用RasDial函數。
其聲明如下:
DWORD Ras Dial(LPRASDIALEXTENSIONS lpRas DialExtensions,LPCTSTR lpszPhonebook,LPRASDIALPARAMS
lp Ras DialParams,DWORD dw Notifier Type,LPVOID lpv Notifier,
LPHRASCONN lph Ras Conn )
參數說明:
lpRasDialExtensions和lpszPhonebook:僅在Windows NT下有效,在Windows 95下,這兩個參數被忽略。
lpRasDialParams:這個參數很重要,它指向一個RASDIALPARAMS結構,該結構包含以下幾個成員:
dwSize:應設定為sizeof(RASDIALPARAMS);
szEntryName和szPhoneNumber:這兩個參數有聯系,szEntryName可以指定要建立的連接,比方說“我的連接”等等,這是處理用戶已經在“撥號網絡”裡建立的連接的。這時,Modem將撥打你在“我的連接”中設定的ISP號碼,此時szPhoneNumber成員設為空字符串“”即可;如果你要在程序中自行指定要撥打的ISP號碼的話,szEntryName可以設定為空字符串“”,此時應設置szPhoneNumber為你的ISP號碼(169,663等),特別的,對於用201電話卡來上網的情況,可以設為“201,,,賬號,密碼#,,ISP號碼#”(其中“,”表示停頓一段時間(以等待確認賬號,密碼等),你可以根據自己所在位置的線路狀況自行調節。
SzCallBackNumber,szDomain:設為空串“”即可。
SzUserName,szPassword:登錄用戶名和密碼。如169公用賬號guest,guest。
其他成員不必設置。
DwNotifierType:指定是由窗口還是由回調函數來處理確認消息。通過確認消息我們可以得到RasDial過程的當前狀態。如“正在打開段口”,“正在驗證用戶名和密碼”等。也可設為NULL。
dwNotifier:指定處理確認消息的窗口或回調函數。也可設為NULL。
LphRasConn:指向一個類型為HRASCONN的變量。在調用RasDial前必須指定為NULL,RasDial若成功返回,則將RAS連接的句柄存放於它所指向的變量中。我們也可以通過此句柄來斷開連接。
只要在程序中適當位置調用RasDial函數即可建立連接。
2. 理確認消息以得到撥號過程的當前狀態。
我們以指定窗口來處理確認消息為例說明如何得到撥號過程的當前狀態。
在處理確認消息的對話框類(或視圖類等)的實現代碼中加入:
const UINT WM_RASEVENT = ::RegisterWindowMessageA(RASDIALEVENT);
在Message Map中手工加入消息映射:(****是你定義的對話框類名稱)
BEGIN_MESSAGE_MAP(****, CDialog)
//AFX_MSG_MAP(****)
……
ON_REGISTERED_MESSAGE(WM_RASEVENT, OnRasDialEvent)(<-加入此句)
//AFX_MSG_MAP
END_MESSAGE_MAP()
加入成員函數處理消息:
LRESULT CDialInfo::OnRasDialEvent(WPARAM wp, LPARAM lp)
{
RASCONNSTATE rasstate= (RASCONNSTATE)wp;
CListBox *info =(CListBox *)GetDlgItem(IDC_INFOLIST);
//用ListBox 控件(ID為IDC-INFOLIST)來顯示狀態)
switch(rasstate)
{
case RASCS_OpenPort:
info→AddString(_T(″打開端口……″));
break;
case RASCS_PortOpened:
info→AddString(_T(″端口已打開.″));
break;
case RASCS_ConnectDevice:
info→AddString(_T(″連接設備……″));
break;
case RASCS_DeviceConnected:
info→AddString(_T(″設備已連接.″));
break;
case RASCS_Authenticate:
info→AddString(_T(″驗證用戶及密碼″));
break;
case RASCS_Authenticated:
info→AddString(_T(″通過″));
break;
case RASCS_Connected:
info->AddString(_T(″已連接″));
reak;
case RASCS_Disconnected:
info->AddString(_T(″連接已斷開″));
m_hRasConn=NULL;
//可定義類型為HRASCONN的成員變量m_hRasConn來保存RAS連接的句柄。
//在調用RasDial時用指向m_hRasConn的指針作為lphRasConn參數。
//既然用m_hRasConn來保存連接句柄,連接斷開後應重置為NULL.
break;
default:
return (LRESULT)0;
}
return (LRESULT)0;
}
3. 斷開連接:
if (m_hRasConn != NULL)
{
RasHangUp(m_hRasConn);
m_hRasConn = NULL;
m_OnDial=TRUE;
:Sleep(2000);
}
注意 :
你也許注意到了以上代碼中的Sleep函數,這裡是必需的。需要一定時間來斷開連接。如果不等待一段時間,計算機有可能無法正常關閉端口。導致下一次無法撥號,只有重新啟動Windows才能解決。要預防此問題也可以調用RasGetConnectStatus函數,方法如下:
RASCONNSTATUS rStatus;
while(RasGetConnectStatus(m_hRasConn,&rStatus)!=ERROR_INVALID_HANDLE)
{
::Sleep(0);
}
4.在以下情況下:
① 浏覽網頁時有時會出現停止響應,重啟explorer後任務欄上的連接狀態圖標也許會消失。
② 希望在連接成功後,退出程序,再次執行此程序可選擇斷開連接。
可以調用RasEnumConnection函數來得到當前連接的句柄。
舉例如下:
HRASCONN hRasConnect;DWORD dwBuffferSize, dwNumofConnections;//緩沖區大小,連接數
LPRASCONN lpRasConn;
lpRasConn = new RASCONN[3】;//最多可得到3個連接句柄,客戶端程序其實不必設為3,因連接數有限,大部分僅一個連接。
lpRasConn[0】.dwSize = sizeof(RASCONN);
dwBuffferSize = 32* sizeof(RASCONN);//求出由3個RASCONN結構構成的緩沖區大小
RasEnumConnections(lpRas Conn, &dw Buffer Size, &dw Numof Connections);//此函數若成功則返回零。
for(DWORD i=0; i {
hRasConnect = lpRasConn[i】.hrasconn;//RASCONN結構的hrasconn成員為RAS連接句柄
RasHangUp(hRasConnect);
::Sleep(2000);
}
delete [】 lpRasConn;
在Windows 98,Visual C++ 6.0下調試通過。
這樣,一個實現基本撥號上網功能的程序就完成了。如果你要了解更多有關情況或服務器端程序設計,可以參考MSDN→Platform SDK→Networking
and Distributed Services→Remote Access Service的有關內容。(csdn)