在程序中实现远程访问控制
作者:xrbeck
远程访问控制(Remote Access Service)是Windows NT,
Win2000 Server提供的一种远程服务,它允许用户从远端
通过拨号连接连接到一个本地的计算机网络,一旦建立了
连接,就相当于处在了本地的LAN中,从而可以使用各种各样
的网络函数以便进行访问,本文就是给大家介绍这种听起来
就很动心的技术。 :)
首先我们需要配置服务器端的RAS服务,在这里以2k Server
为例,第一安装modem,相信大家应该没什么问题吧.装好
modem后,选择"控制面板"中的"网络和拨号连接",新建连接,
选择"接受接入的连接",并且在最后一步添加一个允许登录
的帐号,本文设置用户名:xr 密码:xr,这样就在服务器端
建立了一个"等待接入"的连接,然后右键选择属性,在网络
中选择TCP/IP协议,因为笔者的LAN中是通过代理,静态的分配
保留IP地址172.18.所以在这个地方选择"指定TCP/IP地址"
从'172.18.1.27“到"172.18.1.28"分配两个IP地址.这是
因为VLSM是255.255.255.224,一个LAN中保留30台机器,
选择后面几台未分配的IP地址。打开控制面板中的管理工具,
选择路由和远程访问,选择本地服务器,并且"配置并启用
路由和远程访问",可以查看活动与否的端口.
这样在服务器端就配置好了RAS服务.接下来进入关键
部分:在远端用程序实现RAS连接.同样我们需要电话线和modem.
安装好后我们就能利用系统提供的rasapi实现拨号连接.
以BCB5.0为例:给出源程序如下:
1.连入头文件ras.h,raserror.h和库文件rasapi.lib
这个地方要注意有个版本冲突问题,所以需要临时的设置
WINVER这个变量.具体代码如下:
#define OLDVER WINVER
#undef WINVER
#define WINVER 0x400
#include <ras.h>
#include <raserror.h>
#undef WINVER
#define WINVER OLDVER
#undef OLDVER
静态连入rasapi.lib后,我们就能利用API函数实现拨号了
2. 拨接部分:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
//
hrasconn=NULL;
RASDIALPARAMS params;
char buf[256];
memset(buf,0,256);
params.dwSize=sizeof(RASDIALPARAMS);
lstrcpy(params.szEntryName,"");
lstrcpy(params.szPhoneNumber,"208");
lstrcpy(params.szUserName,"xr");
lstrcpy(params.szPassword,"xr");
lstrcpy(params.szDomain,"");
int ret=RasDial(NULL,
NULL,
¶ms,
0,
&RasDialFunc,
&hrasconn);
if(ret!=0)
{
RasGetErrorString(ret, buf, 256);
memStatus->Lines->Add(buf);
}
}
其中RasDial为异步访问方式,208为笔者测试的公司内部
的服务器的电话号码,xr是登录的用户名和口令,因为
测试的2K Server是作为对等网中的普通一员,没有domain,
所以设置为空.
3. 回调函数部分:
类似大部分的window程序,ras也提供了回调函数来
异步的处理连接,这样的情况很多,比如Winsock也提供
了窗口消息的异步方式.
void WINAPI RasDialFunc(UINT MSG,RASCONNSTATE rasconnstate,DWORD dwError)
{
//
char szRasString[256]; // Buffer for storing the error string
memset(szRasString,0,256);
DWORD cb=sizeof(RASPPPIP);
DWORD ret;
if (dwError) // Error occurred
{
RasGetErrorString((UINT)dwError, szRasString, 256);
Form1->memStatus->Lines->Add(szRasString);
return;
}
switch (rasconnstate)
{
// Running States
case RASCS_OpenPort:
Form1->memStatus->Lines->Add("Opening port...");
break;
case RASCS_PortOpened:
Form1->memStatus->Lines->Add("Port opened.");
break;
case RASCS_Authenticated:
Form1->memStatus->Lines->Add("Authentication complete.");
break;
case RASCS_Connected:
Form1->memStatus->Lines->Add("Connection Connected.");
Form1->lpProjection=new RASPPPIP;
Form1->lpProjection->dwSize=sizeof(RASPPPIP);
if(RasGetProjectionInfo(Form1->hrasconn,RASP_PppIp,Form1->lpProjection,&cb)==ERROR_SUCCESS)
{
Form1->memStatus->Lines->Add("Server IP:"+(AnsiString)(Form1->lpProjection->szServerIpAddress));
Form1->memStatus->Lines->Add("Local IP:"+(AnsiString)(Form1->lpProjection->szIpAddress));
}
break;
case RASCS_Disconnected:
Form1->memStatus->Lines->Add("Disconnecting...");
break;
default:
Form1->memStatus->Lines->Add("Unknown Status ");
break;
}
}
处理各种消息,其中在连接部分使用RasGetProjectionInfo得到连接
分配的IP地址和服务器端的地址.由于是静态的分配的,所以和服务器
端是处于一个子网当中,也就能使用各种各样的资源了,比如说可以使用
WNET系列函数得到LAN中的情况,又或者在Connect事件后建立套接字,
实现传输.笔者测试如下:拔掉客户端的网线后,建立连接后能ping到
LAN中其他的机器,而且由于处于子网中,所以也能上网了,使用IPHelper
函数返回的子网掩码和网关是一致的.
本文为大家介绍了什么是RAS以及如何编程实现RAS服务,无疑这是一项
方便而强大的功能.希望能给大家带来帮助.也欢迎大家进一步继续
讨论.QQ.33854303
测试环境: 客户端BCB5.0+Win98. 服务器端:Win2000 Server
参考书籍: Windows网络编程
Internet与TCP/IP程序设计之C++ Builder高手