首先是用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
聂文龙 阅读(413)
评论(0) 编辑 收藏 引用 所属分类:
Visual C++