首先是用ICMP檢查網(wǎng)絡(luò)是否連通:
bool Util::CheckInternet()
{
char *SendData = "Data Buffer";
LPVOID ReplyBuffer;
DWORD dwRetVal;
HANDLE hIcmpFile;
bool b=false;
if ((hIcmpFile = IcmpCreateFile()) == INVALID_HANDLE_VALUE)
return false;
ReplyBuffer = (VOID*) malloc(sizeof(ICMP_ECHO_REPLY) + sizeof(SendData));
if ((dwRetVal = IcmpSendEcho(hIcmpFile,
inet_addr("209.131.36.158"), //用的雅虎的一個(gè)IP,可能延遲會(huì)大一點(diǎn),用國(guó)內(nèi)的會(huì)小一點(diǎn)
SendData, sizeof(SendData),
NULL, ReplyBuffer,
sizeof(ReplyBuffer) + sizeof(ICMP_ECHO_REPLY),
1000)) != 0) {
b=true;
}
free(ReplyBuffer);
return b;
}
很簡(jiǎn)單的幾行代碼,沒(méi)有注釋;
如果網(wǎng)絡(luò)不通的話枚舉撥號(hào)連接,進(jìn)行撥號(hào):
bool RASManager::ConnectNetwork()
{
RASENTRYNAME Entries[15];
DWORD cb,cEntries,dwRet;
Entries[0].dwSize=sizeof(RASENTRYNAME);
cb=sizeof(Entries);
cEntries=0;
dwRet=::RasEnumEntries(NULL, NULL, &Entries[0], &cb, &cEntries);//如果函數(shù)成功,則返回0
if(dwRet == 0)
{
CHAR szRasEntryName[RAS_MaxEntryName + 1]={0};
for(UINT i=0;i<cEntries;i++)
strcpy(szRasEntryName,Entries[i].szEntryName);
RASDIALPARAMS rdParams;
DWORD dwRet;
hConn=NULL;
rdParams.dwSize=sizeof(RASDIALPARAMS);
strcpy(rdParams.szEntryName,szRasEntryName);
strcpy(rdParams.szPhoneNumber,"#777");//我用的3G卡,撥#777號(hào)碼
strcpy(rdParams.szUserName,"用戶名");
strcpy(rdParams.szPassword,"密碼");
strcpy(rdParams.szDomain,"");//這個(gè)也很重要,指定域,如果不指定這個(gè)的話下面注釋的兩句一定要加上,下邊兩句的意思是獲取最后一次連接成功時(shí)的參數(shù)信息,如果用下邊兩句的話連同這行和這行上面的三行都可以省略
// BOOL fPass;
//RasGetEntryDialParams(NULL, &rdParams,&fPass);
dwRet=RasDial(NULL,NULL,&rdParams,0L,NULL,&hConn);
if(dwRet!=0)
{
return false;
}
return true;
}
else
{
return false;
}
}
預(yù)先建立撥號(hào)連接,以上撥號(hào)代碼經(jīng)過(guò)修改已經(jīng)不需要保存密碼,只建立一個(gè)撥號(hào)連接即可。
Windows XP or later: Do not use the
RasSetEntryDialParams function. MSDN上面的說(shuō)法就是
RasSetEntryDialParams 別在XP之后的系統(tǒng)上使用了。
檢查撥號(hào)連接的狀態(tài),如果已經(jīng)通過(guò)撥號(hào)連接上了網(wǎng)絡(luò)當(dāng)然不用再進(jìn)行撥號(hào)了,代碼如下:
bool RASManager::RasGetConnectStatus()
{
LPRASCONN lpRasConn = NULL;
DWORD cbBuf = 0;
DWORD cConn = 0;
DWORD dwRet = 0;
HRASCONN hrasconn;
bool bResult=FALSE;
RASCONNSTATUS rasStatus;
UINT ndx;
cbBuf = sizeof(RASCONN);
lpRasConn = (LPRASCONN)malloc((UINT)cbBuf);
if (lpRasConn != NULL)
{
lpRasConn->dwSize = sizeof(RASCONN);
dwRet = RasEnumConnections(lpRasConn,&cbBuf,&cConn);
for(ndx=0;ndx<cConn;ndx++)
{
hrasconn = lpRasConn[ndx].hrasconn;
rasStatus.dwSize = sizeof(RASCONNSTATUS);
dwRet = ::RasGetConnectStatus(hrasconn,&rasStatus);
if(dwRet)
bResult=FALSE;
else
{
if(rasStatus.rasconnstate == RASCS_Connected)
bResult=TRUE;
else
bResult=FALSE;
}
}
}
else
bResult=FALSE;
free(lpRasConn);
return bResult;
}
以上判斷是如果檢查到有一個(gè)已經(jīng)連接的撥號(hào)連接就返回了,應(yīng)該不會(huì)有兩個(gè)或者以上的撥號(hào)連接同時(shí)連接,打開(kāi)端口會(huì)失敗的。
還有一個(gè)是斷線:
void RASManager::HungUP()
{
LPRASCONN lpRasConn=NULL;
DWORD cbBuf = 0;
DWORD cConn = 0;
DWORD dwRet = 0;
HRASCONN hrasconn;
RASCONNSTATUS rasStatus;
UINT ndx;
cbBuf = sizeof(RASCONN);
lpRasConn = (LPRASCONN)malloc((UINT)cbBuf);
if(lpRasConn != NULL)
{
lpRasConn->dwSize = sizeof(RASCONN);
dwRet = RasEnumConnections(lpRasConn,&cbBuf,&cConn);
for(ndx=0;ndx<cConn;ndx++)
{
hrasconn = lpRasConn[ndx].hrasconn;
rasStatus.dwSize = sizeof(RASCONNSTATUS);
dwRet = ::RasGetConnectStatus(hrasconn,&rasStatus);
if(!dwRet)
{
if(rasStatus.rasconnstate == RASCS_Connected)
RasHangUp(hrasconn);
}
}
free(lpRasConn);
}
}
這個(gè)沒(méi)什么好說(shuō)的,執(zhí)行關(guān)閉撥號(hào)連接的操作。
用程序創(chuàng)建連接,經(jīng)過(guò)修改,已經(jīng)可以正常創(chuàng)建連接,代碼如下:
bool RASManager::CreateRASLink()
{
LPRASENTRY lpRasEntry = NULL;
DWORD cb = sizeof(RASENTRY);
DWORD dwBufferSize = 0;
DWORD dwRet = 0;
// 取得entry的大小,這句也不知道是不是必須的,因?yàn)閟izeof(RASENTRY)和這里取到的dwBufferSize是一樣的,不過(guò)還是Get一下安全點(diǎn)
RasGetEntryProperties(NULL,"", NULL, &dwBufferSize, NULL, NULL);
if (dwBufferSize == 0)
return false;
lpRasEntry = (LPRASENTRY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize);
if (lpRasEntry == NULL)
return false;
ZeroMemory(lpRasEntry, sizeof(RASENTRY));
lpRasEntry->dwSize = dwBufferSize;
lpRasEntry->dwfOptions = RASEO_RemoteDefaultGateway|RASEO_PreviewPhoneNumber|RASEO_PreviewUserPw; // 這里的幾個(gè)選項(xiàng)挺重要的,RASEO_RemoteDefaultGateway這個(gè)選項(xiàng)把創(chuàng)建的連接設(shè)置為默認(rèn)連接,RASEO_PreviewPhoneNumber對(duì)應(yīng)選項(xiàng)中的提示輸入電話號(hào)碼,RASEO_PreviewUserPw對(duì)應(yīng)選項(xiàng)中的提示用戶名和密碼
lpRasEntry->dwType = RASET_Phone;
lstrcpy(lpRasEntry->szDeviceType, RASDT_Modem);
lstrcpy(lpRasEntry->szDeviceName,"www");
lpRasEntry->dwfNetProtocols = RASNP_Ip;
lpRasEntry->dwFramingProtocol = RASFP_Ppp;
dwRet = RasSetEntryProperties(NULL, "www", lpRasEntry, dwBufferSize, NULL, 0); // 創(chuàng)建連接
//The RasSetEntryProperties function changes the connection information for an entry in the phone book or creates a new phone-book entry.(reference MSDN)
HeapFree(GetProcessHeap(), 0, (LPVOID)lpRasEntry);
if (dwRet != 0)
return false;
return true;
}
上面的代碼到是可以創(chuàng)建一個(gè)撥號(hào)連接,不過(guò)是個(gè)空的,里面沒(méi)用用戶名和密碼等信息,需要用上面的撥號(hào)代碼來(lái)指定撥號(hào)參數(shù),不能使用
RasGetEntryDialParams來(lái)獲取了。上面的代碼基本上是在網(wǎng)絡(luò)上搜索所得,稍加修改,在這里整理一下。
再補(bǔ)充一下刪除連接的操作,代碼如下:
void RASManager::DeletePhoneBookEntry()
{
RASENTRYNAME Entries[15];
DWORD cb,cEntries,dwRet;
Entries[0].dwSize=sizeof(RASENTRYNAME);
cb=sizeof(Entries);
cEntries=0;
dwRet=::RasEnumEntries(NULL, NULL, &Entries[0], &cb, &cEntries);//如果函數(shù)成功,則返回0
if(dwRet == 0)
{
CHAR szRasEntryName[RAS_MaxEntryName + 1]={0};
for(UINT i=0;i<cEntries;i++)
{
strcpy(szRasEntryName,Entries[i].szEntryName);
RasDeleteEntry(NULL,szRasEntryName);
}
}
}
要想實(shí)現(xiàn)自動(dòng)啟動(dòng)撥號(hào)網(wǎng)絡(luò),就要使用Remote Access Service (RAS) API,這個(gè)API最早是在Windows for Workgroup 3.11中出現(xiàn)的,現(xiàn)在它已經(jīng)成為Win32 API的一個(gè)組成部分。該API將整個(gè)撥號(hào)網(wǎng)絡(luò)稱為Phonebook,而每一個(gè)連接稱為PhonebookEntry。你可以使用RasCreatePhonebookEntry來(lái)創(chuàng)建新的連接,用RasDial來(lái)?yè)芴?hào),而RasEnumEntries可以獲得當(dāng)前系統(tǒng)已有的所有連接,使用其它的RAS函數(shù)還可以獲取或設(shè)置連接的參數(shù)。 RasEditPhonebookEntry函數(shù)將激活標(biāo)準(zhǔn)的Windows 95/NT屬性對(duì)話框來(lái)修改連接的屬性。你可以從Win32 API的手冊(cè)找到所有相關(guān)函數(shù)的詳細(xì)介紹。
補(bǔ)充:在windows中一個(gè)撥號(hào)連接即為一個(gè)PhonrbookEntry以下稱為電話薄記錄或是連接。總的這些稱為Phonebook。
posted on 2013-03-17 20:10
聶文龍 閱讀(438)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
Visual C++