拨号上网
实例 11-1 实现拨号上网
本例知识要点:
1. 远程访问服务(RAS)简介
远程访问服务(Remote Access Service 简称RAS)是windows 操作系统提供的系统服务之一,通过电话线可以使单独的计算机接入网络,或通过两个RAS对拨使两个局域网互连。此项服务的功能可以使远程的计算机端点以较低的费用同网络连接。
由于Windows操作系统的大量使用,远程访问服务功能也被广泛应用,在许多具体的应用程序中,均已通过远程访问功能来实现对远程的资源共享等功能。连通远程访问服务,只要从远程客户机拨通拨号网络就可以了,执行挂断就结束连接,鼠标操作Windows 98中的拨号网络就可以直接连通和挂断。但有些时候我们希望在应用程序中RAS拨号和挂断对用户不可见,那么就需要相应的程序控制来实现RAS拨通和挂断。
2. RasDial拨号函数
Windows 98提供了API函数RasDial,调用系统中建好的拨号网络连接,完成RAS拨号,同时提供了API函数RasHangUp断开连接。RasDial的原型如下:
Dword RasDial(LPRASDIALEXTENSIONS lpRasDialExtensions,LPCTSTR lpszPhonebook,LPRASDIALparams lpRasDialParams, dword dwNotifierType, LPVOID lpvNotifier, LPHRASCONN lphRasConn)
函数的第三个参数为指向RASDIALPARAMS型结构体的指针,它提供了配置RAS拨号的参数:第五个参数为拨号完成后执行的回调函数;第六个参数是LPHRASCONN型指针,拨号连接建立好之后将返回此连接的句柄;其他三个参数为NULL即可。函数调用如果成功将返回零,否则返回错误代码,此错误代码的含义可以在头文件RasERROR.h中找到。
lpRasDialExtensions和lpszPhonebook:仅在Windows NT下有效,在Windows 95下,这两个参数被忽略。
lpRasDialParams:这个参数很重要,它指向一个RASDIALPARAMS结构,RASDIALPARAMS型结构体包括7个数据成员:dwSize、szEntryName、szPhoneNumber、szCallNumber、szUserName、szPassWord和szDomain,分别解释如下:
1) szSize:应设定为sizeof(RASDIALPARAMS)。
2) szEntryName和szPhoneNumber:这两个参数有联系,szEntryName可以指定要建立的连接,比方说“我的连接”等等,“我的连接”是用户在Windows 98“拨号网络”里建立的连接。这时,Modem将拨打用户在“我的连接”中设定的ISP号码,此时szPhoneNumber成员设为空字符串“”即可:如果用户要在程序中自行指定要拨打的ISP号码的话,szEntryNumber可以设定为空字符串“”,此时应设置szPhoneNumber为你的ISP号码(163,169等)。
3) szCallBackNumber,szDomain:设为空串“”即可。
4) szUserName,szPassWord:登陆用户名和密码。如169公用guest。
5) dwNotifierType:指定是窗口还是由回调函数来处理确认消息。通过确认消息用户可以得到RasDial过程的当前状态。如“正在打开端口”,“正在验证用户名和密码”等。也可设为NULL。
6) dwNoifier:指定处理确认消息的窗口或回调函数,也可设为NULL。
7) lphRasConn:指向一个类型为HRASCONN的变量。在调用RasDial前必须指定为NULL,RasDial若成功返回,则将RAS连接的句柄存放于它所指向的变量中。用户可以通过此句柄来断开连接。
3. 拨号状态
以指定窗口来处理确认消息为例,说明如何得到拨号过程的当前状态。
在处理确认消息的对话框类(或视图类等)的实现代码中加入:
const UINT WM_RASEVENT = ::RegisterWindowmessageA(RASDIALEVENT);
在Message Map中手工加入消息映射:CDialInfo是用户定义的对话框类名称。
BEGIN_MESSAGE_MAP(CDialInfo, CDialog)
//AFX_MSG_MAP
……
ON_REGISTER_MESSAGE(WM_RASEVENT,OnRasDialEvent)//添加消息
//AFX_MSG_MAP
END_MESSAGE_MAP()
加入成员函数处理消息:
LRESULT CDialInfo::OnRasDialEvent(WPARAM wp,LPARAM lp)
{
RASCONNSTATE rasstate=(RASCONNSTATE)wp;
//用listbox控件(ID为IDC_BOHAOINFO)来显示拨号状态)
CListBox *info=(CListBox *)getdlgitem(IDC_BOHAOINFO);
Switch(rasstate)
{
Case RASCS_OpenPort:
Info->AddString(_T(“打开端口。。。。。。”));
Break;
Case RASCS_Opened:
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_Connected:
Info->AddString(_T(“已连接”));
Break;
Case RASCS_Disconnected:
Info->AddString(_T(“连接已断开”));
Break;
Default:
Return (LRESULT)0;
}
}
4. 断开连接
由于定义了类型为HRASCONN的成员变量m_hRasConn来保存RAS连接的句柄。而且在调用RasDial时用指向m_hRasConn的指针作为lpRasConn参数。因此在拨号连接断开后应将m_hRasConn置为NULL。
If(m_hRasConn!=NULL)
{
RasHangUp(m_hRasConn);
m_hRasConn = NULL;
::Sleep(2000);
}
上述代码中的Sleep函数是必要的,它等待一定时间来断开连接。如果不等待一段时间,计算机有可能无法正常关闭端口。导致下一次无法拨号,只有重新启动Windows才能解决。
本例制作过程
1) 启动Microsoft Visual C++6.0,单击File下拉菜单下的“新建”命令,在“工程”标签下选择MFC APPWizard(exe)。
2) 在“工程名”文本框中输入工程名Dialproc,在“位置”文本框中输入工程地址,单击OK按钮进入新建应用程序向导。
3) 在向导第一步选择Dialog based(对话框),如图11-1所示。第二到第四步接受默认设置。
图11-1
4) 单击“完成”按钮,单击项目工程区的类视图ResourceView,展开Dialog中的IDD_DIALPRO_DIALOG对话框,清除对话框中的所有控件,并用控件工具栏中的工具增加如图11-2所示的对话框。
图11-2
IDD_DIALPRO_DIALOG对话框中的控件分别是:
文本框 标识:IDC_STATIC 标题:拨号连接
组合框 标识:IDC_DIALUP_COMBO
文本框 标识:IDC_STATIC 标题:用户
编辑框 标识:IDC_USER_EDIT
文本框 标识:IDC_STATIC 标题:密码
编辑框 标识:IDC_PASSWORD_EDIT
按钮 标识:IDC_CONNECT_BUTTON 标题:连接
按钮 标识:IDCANCEL 标题:退出
1.给新添加的控件增加成员变量
1)给控件IDC_DIALUP_COMBO增加成员变量,按住Ctrl键并双击该控件,弹出Add Member Variable对话框,在Member Variable Name中输入m_DialCombo,Category列表框选择Control,如图11-3所示,单击OK按钮确认。
图11-3
2)给控件IDC_USER_EDIT增加成员变量,按住Ctrl键双击该控件,弹出Add Member Variable对话框,在Member Variable Name中输入m_UserID,Category列表框选择Control,如图11-4所示,单击OK按钮确认。
图11-4
3) 给控件IDC_PASSWORD_EDIT增加成员变量,按住Ctrl键双击该控件,弹出Add Member Variable对话框,在Member Variable Name中输入m_Password,Category列表框选择Control,如图11-5所示,单击OK按钮确认。
图11-5
2.给类添加成员函数
1)给类CDialprocDlg添加成员函数SetupDialupCombo()。
在dialprocDlg.h增加成员函数SetupDialupCombo()的说明:
#include <ras.h>
…
Public:
void SetupDialupCombo(void);
…
在dialprocDlg.cpp中编辑成员函数SetupDialupCombo()。
Void CDialprocDlg::SetupDialupCombo()
{
DWORD n;
DWORD dwSize=0;
m_DialCombo.Resetcontent();
DWORD ret=RasEnumEntries(NULL,NULL,NULL,&dwSize, &n);
n=dwSize/sizeof(RASENTRYNAME);
RASENTRYNAME *entry=new RASENTRYNAME[n];
if(entry)
{
entry[0].dwSize=sizeof(RASENTRYNAME);
DWORD ret=RasEnumEntries(NULL,NULL,entry,&dwSize, &n);
for(DWORD i=0; i<n;i++)
{
m_DialCombo.AddString(entry[i].szEntryName);
}
delete[] entry;
}
}
2) 打开ClassWizard, Class Name选择CDialprocDlg,Object IDs 选择 IDC_CONNECT_BUTTON,Messages 选择 BN_CLICKED,单击Add Function按钮,在类CDialprocDlg增加成员函数OnConnectbutton();
void CDialprocDlg::OnConnectButton()
{
//TODO:Add your control notification handler code here
CWaitCursor wait;
RASDIALPARAMS params;
memset(¶ms,’/0’,sizeof(params));
param.dwSize=sizeof(params);
m_DialCombo.GetWindowText(params.szEntryName,sizeof(params.szEntryName)-1);
strcpy(params.szPhoneNumber,””);
m_UserID.GetWindowText(params.szUserName,sizeof(params.szUserName)-1);
m_Password.GetWindowText(params.szPassword,sizeof(params.szPassword)-1);
HRASCONN handle;
if(RasDial(NULL,NULL,¶ms,NULL,NULL,&handle)==0){
MessageBox(“已经连接成功,按确定将切断电话”);
}
else
{
MessageBox(“您拨的计算机没有应答,请稍候再拨”);
}
wait.Restore();
RasHangUp(handle);
}
3) 打开ClassWizard, Class Name选择CDialprocDlg,Object IDs 选择 IDC_DIALUP_COMBO,Messages 选择 CBN_SELCHANGE,单击Add Function按钮,在类CDialprocDlg增加成员函数OnSelchangeDialupCombo();
void CDialprocDlg::OnSelchangeDialupCombo ()
{
//TODO:Add your control notification handler code here
RASDIALPARAMS params;
int sel;
memset(¶ms,’/0’,sizeof(params));
params.dwSize=sizeof(RASDIALPARAMS);
sel=m_DialCombo.GetCurSel();
if(sel>=0){
m_DialCombo.GetLBText(sel,params.szEntryName);
TRACE(“%s/n”,params.szEntryName);
BOOL p;
RasGetEntryDialParams(NULL,¶ms,&p);
m_UserID.SetWindowText(params.szUserName);
m_Password.SetWindowText(params.szPassword);
}
4) 打开ClassWizard, Class Name选择CDialprocDlg,Object IDs 选择 CDialprocDlg,Messages 选择 CBN_SELCHANGE,单击Add Function按钮,在类CDialprocDlg自动增加成员函数OnInitDialog();
BOOL CDialprocDlg:;OnInitDialog()
{
CDialog::OnInitDialog();
//Add”About….”menu item to system menu.
//IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT((IDM_ABOUTBOX<0xF000);
CMenu *pSysMenu = GetSystemMenu(FALSE);
if(pSysMenu!=NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!strAboutMenu.Isempty())
{
pSysMenu->appendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX, strAboutMenu);
}
}
//Set the icon for this dialog. The framework does this automatically
//when the application’s main window is not a dialog
SetIcon(m_hIcon, TRUE); //set big icon
SetIcon(m_hIcon, FALSE); //set small icon
// TODO:Add extra initialization here
SetupDialupCombo();
return TRUE; //return false unless you set the focus to the control
}
3. 增加rasapi32.lib, 单击Project菜单,选择Setting,弹出Project settings对话框,在Settings 对话框中选择Link选项,在Object/Library modules中键入rasapi32.lib,如图11-6 所示。
图11-6
单击build下拉菜单的Excute dialproc.exe命令编译执行文件,就可以在组合框中选择机器上已有的连接进行拨号上网了。
相关阅读
H3C ER2100路由器拨号上网设置 H3C路由器共享上网设置
首先介绍下整个网络的物理结构连接(如下图),外网的WAN线连接到路由器的WAN口上,网络中的电脑或者交换机连接到路由器的LAN口上。下面