首先是用ICMP檢查網絡是否連通:
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"), //用的雅虎的一個IP,可能延遲會大一點,用國內的會小一點
SendData, sizeof(SendData),
NULL, ReplyBuffer,
sizeof(ReplyBuffer) + sizeof(ICMP_ECHO_REPLY),
1000)) != 0) {
b=true;
}
free(ReplyBuffer);
return b;
}
很簡單的幾行代碼,沒有注釋;
如果網絡不通的話枚舉撥號連接,進行撥號:
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);//如果函數成功,則返回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號碼
strcpy(rdParams.szUserName,"用戶名");
strcpy(rdParams.szPassword,"密碼");
strcpy(rdParams.szDomain,"");//這個也很重要,指定域,如果不指定這個的話下面注釋的兩句一定要加上,下邊兩句的意思是獲取最后一次連接成功時的參數信息,如果用下邊兩句的話連同這行和這行上面的三行都可以省略
// BOOL fPass;
//RasGetEntryDialParams(NULL, &rdParams,&fPass);
dwRet=RasDial(NULL,NULL,&rdParams,0L,NULL,&hConn);
if(dwRet!=0)
{
return false;
}
return true;
}
else
{
return false;
}
}
預先建立撥號連接,以上撥號代碼經過修改已經不需要保存密碼,只建立一個撥號連接即可。
Windows XP or later: Do not use the
RasSetEntryDialParams function. MSDN上面的說法就是
RasSetEntryDialParams 別在XP之后的系統上使用了。
檢查撥號連接的狀態,如果已經通過撥號連接上了網絡當然不用再進行撥號了,代碼如下:
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;
}
以上判斷是如果檢查到有一個已經連接的撥號連接就返回了,應該不會有兩個或者以上的撥號連接同時連接,打開端口會失敗的。
還有一個是斷線:
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);
}
}
這個沒什么好說的,執行關閉撥號連接的操作。
用程序創建連接,經過修改,已經可以正常創建連接,代碼如下:
bool RASManager::CreateRASLink()
{
LPRASENTRY lpRasEntry = NULL;
DWORD cb = sizeof(RASENTRY);
DWORD dwBufferSize = 0;
DWORD dwRet = 0;
// 取得entry的大小,這句也不知道是不是必須的,因為sizeof(RASENTRY)和這里取到的dwBufferSize是一樣的,不過還是Get一下安全點
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; // 這里的幾個選項挺重要的,RASEO_RemoteDefaultGateway這個選項把創建的連接設置為默認連接,RASEO_PreviewPhoneNumber對應選項中的提示輸入電話號碼,RASEO_PreviewUserPw對應選項中的提示用戶名和密碼
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); // 創建連接
//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;
}
上面的代碼到是可以創建一個撥號連接,不過是個空的,里面沒用用戶名和密碼等信息,需要用上面的撥號代碼來指定撥號參數,不能使用
RasGetEntryDialParams來獲取了。上面的代碼基本上是在網絡上搜索所得,稍加修改,在這里整理一下。
再補充一下刪除連接的操作,代碼如下:
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);//如果函數成功,則返回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);
}
}
}
要想實現自動啟動撥號網絡,就要使用Remote Access Service (RAS) API,這個API最早是在Windows for Workgroup 3.11中出現的,現在它已經成為Win32 API的一個組成部分。該API將整個撥號網絡稱為Phonebook,而每一個連接稱為PhonebookEntry。你可以使用RasCreatePhonebookEntry來創建新的連接,用RasDial來撥號,而RasEnumEntries可以獲得當前系統已有的所有連接,使用其它的RAS函數還可以獲取或設置連接的參數。 RasEditPhonebookEntry函數將激活標準的Windows 95/NT屬性對話框來修改連接的屬性。你可以從Win32 API的手冊找到所有相關函數的詳細介紹。
補充:在windows中一個撥號連接即為一個PhonrbookEntry以下稱為電話薄記錄或是連接。總的這些稱為Phonebook。
posted on 2013-03-17 20:10
聶文龍 閱讀(421)
評論(0) 編輯 收藏 引用 所屬分類:
Visual C++