发信人: krh2001.lpfdiyvbb()
整理人: wenbobo(2003-08-23 10:58:23), 站内信件
|
【 在 wangwei_hy 的大作中提到:】
:请教:使用Modem上网怎样获得Modem自动分配的IP地址 (注:在VC++的开发环境中)
:......
要使用下面的函数必须包含"ras.h",并指定外部库链接"rasapi32.lib".
相关的函数和数据结构如下:
typedef struct _RASCONN {
DWORD dwSize; //sizeof(RASCONN),即本结构的字节数。
HRASCONN hrasconn; //连接句柄,RasGetProjectionInfo函数获取IP时需要的一个参数。
TCHAR szEntryName[RAS_MaxEntryName + 1]; //入口名,在获取IP时并不需要它
#if (WINVER >= 0x400)
CHAR szDeviceType[ RAS_MaxDeviceType + 1 ]; //设备类型,在获取IP时并不需要它
CHAR szDeviceName[ RAS_MaxDeviceName + 1 ]; //设备名,在获取IP时并不需要它
#endif
} RASCONN
DWORD RasEnumConnections(
LPRASCONN lprasconn, //接收到的连接数据缓冲区,该缓冲区应分配为
//最多能存在的连接数*sizeof(RASCONN)
//(对于存在多个连接的用户,可以是RASCONN结构数组的首地址)
LPDWORD lpcb, //缓冲区尺寸(是一个数据指针)即(*lpcb)=sizeof(RASCONN)*存在的连接数
LPDWORD lpcConnections//它指示向第一个参数指向的缓冲区实际填写的RASCONN结构数量。
);
-------------------------------------------------------------------
typedef struct _RASAMB {
DWORD dwSize;
DWORD dwError;
TCHAR szNetBiosError[ NETBIOS_NAME_LEN + 1 ];
BYTE bLana;
} RASAMB;
typedef struct _RASPPPNBF {
DWORD dwSize;
DWORD dwError;
DWORD dwNetBiosError;
TCHAR szNetBiosError[ NETBIOS_NAME_LEN + 1 ];
TCHAR szWorkstationName[ NETBIOS_NAME_LEN + 1 ];
BYTE bLana;
} RASPPPNBF;
typedef struct _RASPPPIPX {
DWORD dwSize;
DWORD dwError;
TCHAR szIpxAddress[ RAS_MaxIpxAddress + 1 ];
} RASPPPIPX;
对于只使用tcp/ip协议的同志,上面的三个结构就不需要啦。
--------------------------------------------------------------------
typedef struct _RASPPPIP {
DWORD dwSize;
DWORD dwError;
TCHAR szIpAddress[ RAS_MaxIpAddress + 1 ]; //这里就是我们需要的IP地址。
#ifndef WINNT35COMPATIBLE
CHAR szServerIpAddress[ RAS_MaxIpAddress + 1 ]; //这里还可获得服务端IP。
#endif
} RASPPPIP;
typedef enum _RASPROJECTION {
RASP_Amb = 0x10000, //对应的接收结构是 RASAMB NETBIOS协议
RASP_PppNbf = 0x803F, //对应的接收结构是 RASPPPNBF NETBIOS协议
RASP_PppIpx = 0x802B, //对应的接收结构是 RASPPPIPX SPX/IPX协议
RASP_PppIp = 0x8021 //对应的接收结构是 RASPPPIP TCP/IP协议
RASP_Slip = 0x20000 //没有对应的结构
} RASPROJECTION ;
DWORD RasGetProjectionInfo(
HRASCONN hrasconn, //可以从RasEnumConnections获取的信息中得到
RASPROJECTION rasprojection, //规定获取的信息的类型,是个枚举值
LPVOID lpprojection, //接受缓冲区的指针,具体结构与上一个参数相关
LPDWORD lpcb //缓冲区尺寸(是一个数据指针)即(*lpcb)=sizeof(接收信息结构)
//也于第一个参数有关,但该值由调用者填写。
);
附:一段获取动态IP的C++代码
由于时间关系,获取动态IP部分的容错处理不是很完善。各位在自己的代码中可适当增加一些出错处理和
一些断言。
void CMyMFCDlg::OnInitserve()
{
CString InfoStr;
RASCONN rasconn;
DWORD connnum;
DWORD strucsize=sizeof(RASCONN);
if (!RasEnumConnections(&rasconn,&strucsize,&connnum)) //获取拨号动态IP,假定只有一个连接。
{
RASPPPIP ipinfo;
DWORD ipinfosize=sizeof(RASPPPIP);
ipinfo.dwSize=sizeof(RASPPPIP);
if (!RasGetProjectionInfo(rasconn.hrasconn,RASP_PppIp,(LPVOID)&ipinfo,&ipinfosize))
{
InfoStr.Format("%s%d","无法获取拨号IP,返回错误码为:",
::GetLastError());
MessageBox(InfoStr,"错误",MB_ICONSTOP );
}
else
{
InfoStr=ipinfo.szIpAddress;
}
}
else
{
m_ListenAddress.GetLBText(m_ListenAddress.GetCurSel(),InfoStr.GetBuffer(20));
InfoStr.ReleaseBuffer();
}
if (!InfoStr.IsEmpty())
{
CMyMFCApp * pApp=(CMyMFCApp*)AfxGetApp();
if (pApp->m_ServSock.m_hSocket==INVALID_SOCKET) //这里可以用断言代替条件语句;
{
if (pApp->m_ServSock.Create(1200,SOCK_STREAM ,InfoStr))
{ //服务端SOCKET建立成功.
if (pApp->m_ServSock.Listen ())
{ //在该端口监听成功
GetDlgItem(IDC_INITSERVE)->EnableWindow(FALSE);
InfoStr="服务端初始化完成,开始在1200端口监听";
int len=InfoStr.GetLength();
SetDlgItemText(IDC_SERVEDIT,InfoStr);
GetDlgItem(IDC_CLIENT)->EnableWindow(TRUE); //用于单机调试时,
} //进行客户端和服务端同步。
else
{
InfoStr.Format("%s%d","监听失败,返回错误码为:",
CSocket::GetLastError());
MessageBox(InfoStr,"错误",MB_ICONSTOP );
}
}
else
{
InfoStr.Format("%s%d","服务端SOCKET建立失败,返回错误码为:",
CSocket::GetLastError());
MessageBox(InfoStr,"错误",MB_ICONSTOP);
}
}
else
{
InfoStr.Format("%s","服务端SOCKET对象已经建立");
MessageBox(InfoStr,"注意",MB_ICONINFORMATION );
}
}
else
{
InfoStr.Format("%s","请选择一个监听地址");
MessageBox(InfoStr,"对不起",MB_ICONINFORMATION);
}
// TODO: Add your control notification handler code here
}
----
|
|