用VC++实现拨号连接及动态IP 地址获取

发表于:2007-07-04来源:作者:点击数: 标签:
福建师范大学社会学系 许春漫 在Win32 API 函数中有一组用于实现远程连接服务RAS 的函数,利用这些函数通过编程可以实现建立和Internet 的拨号连接,并可获得Internet 分配给主机的动态IP 地址。 一、建立拨号连接API 建立拨号连接是利用函数RasDial() 实现的
福建师范大学社会学系 许春漫

  在Win32 API 函数中有一组用于实现远程连接服务RAS 的函数,利用这些函数通过编程可以实现建立和Internet 的拨号连接,并可获得Internet 分配给主机的动态IP 地址。

一、建立拨号连接API

  建立拨号连接是利用函数RasDial() 实现的,该函数调用后立即返回,若成功返回0 值,否则返回非0 值。在拨号连接过程中,回调函数接收连接的状态信息及发生的错误代码。回调函数的原形如下:VOID WINAPI RasDialFunc(UINT unMsg,RASCONNSTATE rasconnstate,DWORD dwError)
  由于在调用RasDialFunc 函数时,连接操作被挂起,因此,应用程序应尽快处理发生的事件并返回。可以在RasDialFunc 函数中调用PostMessage 函数,将事件通知消息送给窗口函数来处理。

  RASDIALPARAMS 结构定义如下:

  DWORD dwSize 结构变量的大小。

  TCHAR szEntryName[RAS_MaxEntryName +1]   拨号网络中建立的连接名。

  TCHAR szPhoneNumber[RAS_MaxPhoneNumber +1] 电话号码,若采用szEntryName 中定义的号码,置为NULL 值。

  TCHAR szCallbackNumber[RAS_MaxCallbackNumber +1] 回拨号码,不用时置为NULL。

  TCHAR szUserName[UNLEN +1] 用户标识。

  TCHAR szPassword[PWLEN +1] 用户口令。

  TCHAR szDomain[DNLEN +1] 用户权限验证域,若为NULL 采用RAS 服务器所在的域进行验证,若为‘*’采用szEntryName 中定义的域进行验证。

  RASCONNSTATE 枚举型结构,包含拨号连接过程中各种可能状态的定义。

  函数RasHangUp() 用来终止拨号连接,因程序需要一定的时间来结束连接,应用程序调用该函数后不能马上退出,需等待3 秒后才能退出。

二、获取动态IP 地址API

  在VC 中是通过调用函数RasGetProjectionInfo() 来获取IP 地址的。
  函数调用成功时返回0 值,此时在RASPPPIP 结构变量中的szIpAddress 就是动态IP 地址。

三、程序实现

  程序是在Win 95 环境下,用VC ++5.0 编写,并编译运行通过。完整的源程序清单如下:
// --- -------------
//file name ras.c
// --- -------------
#include < windows.h >
#include < winuser.h >
#include < string.h >
#include < ras.h >
#include < raserror.h >
#include "resource.h"
// 函数原形
LRESULT CALLBACK DialogProc(HWND hDlg,
UINT message, WPARAM wParam, LPARAM lParam);
void ShowMsg(HWND hwnd,char *msg);
LRESULT MsgDialDlgEvent(HWND hdlg,
UINT uMessage, WPARAM wparam, LPARAM lparam);
VOID WINAPI RasDialFunc
( UINT unMsg, RASCONNSTATE rasconnstate,
 DWORD dwError );
BOOL StartCon( HWND hWnd,char
      *szUser,char *szPassword );
UINT GetRasConnState( RASCONNSTATE rasconn );
// 全局变量
HRASCONN  hCon; //RAS 连接句柄
HWND    hWin;
HINSTANCE  hInst;
// --- --------------
//windows 入口函数
// --- --------------
int PASCAL WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,LPSTR lpszCmdLine,
int nCmdShow )
{
   hInst=hInstance;
   if ( DialogBox(hInstance,"RAS_DLG",NULL,
   (DLGPROC)DialogProc) == -1 )
   MessageBox(NULL,"建立对话框失败!",
   "TITLE",MB_OK);
   return 0;
}
// -----------------
// 对话框窗口函数
// -----------------
LRESULT CALLBACK DialogProc(HWND hDlg,
UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
   case WM_INITDIALOG:
     hWin=hDlg;
     hCon=NULL;
     return (TRUE);
   case WM_RASDIALEVENT:
     MsgDialDlgEvent(hDlg,message,wParam,lParam);
     return (TRUE);
   case WM_COMMAND:
     switch (LOWORD(wParam))
     {
   case IDOK:
     StartCon( hDlg,"ljx@public.smptt.fj.cn",
"abbcd");
     break;
   case IDCANCEL:
     if ( hCon != NULL )
     {
     RasHangUp(hCon);
     Sleep(3000);
     }
     EndDialog(hDlg,TRUE);
     break;
     }
     break;
   }
   return (FALSE);
}
// ****************
// 在列表框中显示信息
// ****************
void ShowMsg(HWND hwnd,char *msg)
{
   int lnum;
   SendDlgItemMessage(hwnd,IDC_MSG,
   LB_ADD ?STRING,0,(long)msg );
 lnum=SendDlgItemMessage(hwnd,IDC_MSG,
   LB_GETCOUNT, 0,0);
   SendDlgItemMessage(hwnd,IDC_MSG,LB_SET ?
CURSEL,lnum -1,0);
   return;
}
// -----------------
// BOOL StartCon( HWND hWnd )
// 建立拨号连接, 成功TRUE else FALSE
// szUser 和szPassword 分别为
 Internet 的用户名和口令
// -----------------
BOOL StartCon
( HWND hWnd,char *szUser,char *szPassword )
{
  RASDIALPARAMS rdParams;
  DWORD dwRet;
   char szBuf[300];
   // 初始化变量
  rdParams.dwSize = sizeof(RASDIALPARAMS);
  lstrcpy(rdParams.szEntryName, "internet");
  rdParams.szPhoneNumber[0] = '\0';
  rdParams.szCallbackNumber[0] = '*';
  rdParams.szCallbackNumber[0] = '\0';
  strcpy(rdParams.szUserName,szUser);
  strcpy(rdParams.szPassword,szPassword);
   rdParams.szDomain[0] = '\0';
   hCon=NULL;
   // 以下开始异步拨叫网络
  dwRet = RasDial( NULL, NULL, &rdParams, 0L,
      (RASDIALFUNC) RasDialFunc, &hCon );
  if ( dwRet )
  {
  if ( RasGetErrorString( (UINT)dwRet,
     (LPSTR)szBuf, 256 ) != 0 )
   wsprintf( (LPSTR)szBuf,
   “Undefined RAS Dial Error ( %ld).", dwRet );
   ShowMsg(hWnd,szBuf);
   return FALSE;
  }
   return TRUE;
}
// ---------------
// RasDial 异步处理的回调函数
// unMsg -发生的RAS 事件
// rasconnstate -连接进入的状态
// dwError   -发生的错误代码
// ---------------
VOID WINAPI RasDialFunc
( UINT unMsg, RASCONNSTATE rasconnstate,
DWORD dwError )
{
  PostMessage(hWin,
       WM_RASDIALEVENT,
       (WPARAM) rasconnstate,
       (LPARAM) dwError );
}
// ----------------
// RasDial() 返回的事件信息由该函数处理
// ----------------
LRESULT MsgDialDlgEvent(HWND hdlg, UINT uMessage,
WPARAM wparam, LPARAM lparam)
{
RASPPPIP rip;
DWORD ll,ret;
int num;
char szMessage[256];
LoadString(hInst,GetRasConnState
( (RASCONNSTATE) wparam ), szMessage, 64 );
ShowMsg(hdlg,szMessage);
if ( lparam ) // 发生错误
{
   if ( RasGetErrorString
   ( (UINT)lparam, szMessage, 256 ) != 0 )
   wsprintf( (LPSTR)szMessage,
   “出错Undefined RAS Dial Error." );
   ShowMsg(hdlg,szMessage);
      return TRUE;
         
  }
  else if ( RASCS_DONE &wparam ) // 连接成功
  {
   // 取动态分配的IP 地址
   ShowMsg(hdlg,"连接成功");
   rip.dwSize=sizeof(RASPPPIP);
    if((ret=RasGetProjectionInfo(hCon,RASP_PppIp,
   (LPVOID) &rip,(LPDWORD) &ll )) != 0 )
    {
   ShowMsg(hdlg,"取IP 地址失败");
   }
   else
   ShowMsg(hdlg,rip.szIpAddress);
  }
  return TRUE;
}
// ----------------
// 根据连接状态
 取字符串资源中对应的标号
// ----------------
UINT GetRasConnState( RASCONNSTATE rasconn )
{
  switch( rasconn )
  {
    case RASCS_OpenPort:
      return IDS_OPENPORT;
    case RASCS_PortOpened:
      return IDS_PORTOPENED;
    case RASCS_ConnectDevice:
      return IDS_CONNECTDEVICE;
    case RASCS_DeviceConnected:
      return IDS_DEVICECONNECTED;
    case RASCS_AllDevicesConnected:
      return IDS_ALLDEVICESCONNECTED;
    case RASCS_Authenticate:
      return IDS_AUTHENTICATE;
    case RASCS_AuthNotify:
      return IDS_AUTHNOTIFY;
    case RASCS_AuthRetry:
      return IDS_AUTHRETRY;
    case RASCS_AuthCallback:
      return IDS_AUTHCALLBACK;
    case RASCS_AuthChangePassword:
      return IDS_AUTHCHANGEPASSWORD;
    case RASCS_AuthProject:
      return IDS_AUTHPROJECT;
    case RASCS_AuthLinkSpeed:
      return IDS_AUTHLINKSPEED;
    case RASCS_AuthAck:
      return IDS_AUTHACK;
    case RASCS_ReAuthenticate:
      return IDS_REAUTHENTICATE;
    case RASCS_Authenticated:
      return IDS_AUTHENTICATED;
    case RASCS_PrepareForCallback:
      return IDS_PREPAREFORCALLBACK;
    case RASCS_WaitForModemReset:
      return IDS_WAITFORMODEMRESET;
    case RASCS_WaitForCallback:
      return IDS_WAITFORCALLBACK;
    case RASCS_Interactive:
      return IDS_INTERACTIVE;
    case RASCS_RetryAuthentication:
      return IDS_RETRYAUTHENTICATION;
    case RASCS_CallbackSetByCaller:
      return IDS_CALLBACKSETBYCALLER;
    case RASCS_PasswordExpired:
      return IDS_PASSWORDEXPIRED;
    case RASCS_Connected:
      return IDS_CONNECTED;
    case RASCS_Disconnected:
      return IDS_DISCONNECTED;
    default:
      return IDS_UNDEFINED_ERROR;
  }
}  

原文转自:http://www.ltesting.net