无须SMTP服务器中转直接发送电子邮件
2009-01-21 20:00:52 来源:WEB开发网我们要完成几项编程工作:本机DNS的获取、与DNS服务器通信实现MX指令查询、SMTP邮件提交,下面我们一一阐述。
获取本机DNS
代码中我封装了一个类CnetAdapterInfo,该类可以获取本机网卡的系列信息,包括本机IP地址、子网掩码、DNS、Wins、网卡MAC地址等相关信息。
首先我们需要调用IPHelpAPI 库中的GetAdaptersInfo()函数来获取系统中所有网卡信息。
DWORD GetAdaptersInfo (
__out PIP_ADAPTER_INFO pAdapterInfo,
__inout PULONG pOutBufLen
);
该函数有两个参数,pAdapterInfo是一个指针,指向一个用户定义的结构体,一般是用HeapAlloc()申请的内存空间,pOutBufLen传入pAdapterInfo所指空间的大小,传出实际需要的缓冲大小,第一次调用该函数时pOutBufLen传入0,函数将返回 ERROR_BUFFER_OVERFLOW 表示需要更多的缓冲,并将实际需要的缓冲长度返回,我们根据实际长度用HeapAlloc()函数申请空间再次调用该函数,以下代码是枚举所有网卡并将信息保存到数组 m_Ary_NetAdapterInfo 中:
#define MALLOC( bytes ) ::HeapAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, (bytes) )
针对每个网卡信息,我们需要调用 GetPerAdapterInfo()函数来获取指定网卡的DNS信息,使用方法和GetAdaptersInfo()类似。以下代码获取网卡基本信息:
#define FREE( ptr ) if( ptr ) ::HeapFree( ::GetProcessHeap(), 0, ptr )
#define REMALLOC( ptr, bytes ) ::HeapReAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, bytes )
//
// 枚举网络适配器
// return : ------------------------------------------------------------
// -1 - 失败
// >=0 - 网络适配器数量
//
int CNetAdapterInfo::EnumNetworkAdapters ()
{
DeleteAllNetAdapterInfo ();
IP_ADAPTER_INFO* pAdptInfo = NULL;
IP_ADAPTER_INFO* pNextAd = NULL;
ULONG ulLen = 0;
int nCnt = 0;
DWORD dwError = ::GetAdaptersInfo ( pAdptInfo, &ulLen );
if( dwError != ERROR_BUFFER_OVERFLOW ) return -1;
pAdptInfo = ( IP_ADAPTER_INFO* )MALLOC ( ulLen );
dwError = ::GetAdaptersInfo( pAdptInfo, &ulLen );
if ( dwError != ERROR_SUCCESS ) return -1;
pNextAd = pAdptInfo;
while( pNextAd )
{
COneNetAdapterInfo *pOneNetAdapterInfo = new COneNetAdapterInfo ( pNextAd );
if ( pOneNetAdapterInfo )
{
m_Ary_NetAdapterInfo.Add ( pOneNetAdapterInfo );
}
nCnt ++;
pNextAd = pNextAd->Next;
}
// free any memory we allocated from the heap before
// exit. we wouldn't wanna leave memory leaks now would we? ;p
FREE( pAdptInfo );
return nCnt;
}//
// 根据传入的 pAdptInfo 信息来获取指定网卡的基本信息
//
BOOL COneNetAdapterInfo::Init ()
{
IP_ADDR_STRING* pNext = NULL;
IP_PER_ADAPTER_INFO* pPerAdapt = NULL;
ULONG ulLen = 0;
DWORD dwErr = ERROR_SUCCESS;
ASSERT ( m_AdptInfo.AddressLength > 0 );
t_IPINFO iphold;
// 将变量清空
m_bInitOk = FALSE;
m_csName.Empty ();
m_csDesc.Empty ();
m_CurIPInfo.csIP.Empty ();
m_CurIPInfo.csSubnet.Empty ();
m_Ary_IP.RemoveAll ();
m_Ary_DNS.RemoveAll ();
m_Ary_Gateway.RemoveAll ();
#ifndef _UNICODE
m_csName = m_AdptInfo.AdapterName;
m_csDesc = m_AdptInfo.Description;
#else
USES_CONVERSION;
m_csName = A2W ( m_AdptInfo.AdapterName );
m_csDesc = A2W ( m_AdptInfo.Description );
#endif
// 获取当前正在使用的IP地址
if ( m_AdptInfo.CurrentIpAddress )
{
m_CurIPInfo.csIP = m_AdptInfo.CurrentIpAddress->IpAddress.String;
m_CurIPInfo.csSubnet = m_AdptInfo.CurrentIpAddress->IpMask.String;
}
else
{
m_CurIPInfo.csIP = _T("0.0.0.0");
m_CurIPInfo.csSubnet = _T("0.0.0.0");
}
// 获取本网卡中所有的IP地址
pNext = &( m_AdptInfo.IpAddressList );
while ( pNext )
{
iphold.csIP = pNext->IpAddress.String;
iphold.csSubnet = pNext->IpMask.String;
m_Ary_IP.Add ( iphold );
pNext = pNext->Next;
}
// 获取本网卡中所有的网关信息
pNext = &( m_AdptInfo.GatewayList );
while ( pNext )
{
m_Ary_Gateway.Add ( pNext->IpAddress.String );
pNext = pNext->Next;
}
// 获取本网卡中所有的 DNS
dwErr = ::GetPerAdapterInfo ( m_AdptInfo.Index, pPerAdapt, &ulLen );
if( dwErr == ERROR_BUFFER_OVERFLOW )
{
pPerAdapt = ( IP_PER_ADAPTER_INFO* ) MALLOC( ulLen );
dwErr = ::GetPerAdapterInfo( m_AdptInfo.Index, pPerAdapt, &ulLen );
// if we succeed than we need to drop into our loop
// and fill the dns array will all available IP
// addresses.
if( dwErr == ERROR_SUCCESS )
{
pNext = &( pPerAdapt->DnsServerList );
while( pNext )
{
m_Ary_DNS.Add( pNext->IpAddress.String );
pNext = pNext->Next;
}
m_bInitOk = TRUE;
}
// this is done outside the dwErr == ERROR_SUCCES just in case. the macro
// uses NULL pointer checking so it is ok if pPerAdapt was never allocated.
FREE( pPerAdapt );
}
return m_bInitOk;
}
至此我们已经获取到系统中所有DNS服务器地址了。
更多精彩
赞助商链接