这是一个IPV4协议地址族封装,具体也不多说了,看代码就知道了,觉得乱的朋友拷贝下来,贴到VC中看就好了,看到有的朋友贴代码还有折叠着色功能,不知道是用的什么工具,甚是羡慕,知道的告诉我一下吧,大家的支持是我的动力.
/////////////////////////////////////////H//////////////////////////////////////////////////////
#ifndef LGLIB_SOCKETADDRESS_H
#define LGLIB_SOCKETADDRESS_H
#include <winsock2.h>
#include"lg_SyncLock.h"
#include<string>
#include<vector>
//---------------------------------------------------------------------------
using namespace std;
namespace lglib {
class __LGLIB__ lg_SocketEnv
{
public:
lg_SocketEnv( void ) {
// Startup windows sockets
WSADATA wsaData;
int err;
err = WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
if (err==0){
if ((LOBYTE(wsaData.wVersion)==2) && (HIBYTE(wsaData.wVersion)==2)){
// 确认WinSock DLL支持2.0
}else{
//MessageBox(NULL,"该系统不支持网络多播","网络初始化错误",MB_OK);
WSACleanup();
err = WSAVERNOTSUPPORTED; /* 不支持,失败返回 */
}
}
}
~lg_SocketEnv( void ) {
// Shutdown windows sockets
::WSACleanup();
}
};
/*!
* 这是一个独立类模块,可以直接使用。主要提供了主机名->地址或者地址->主机名
* 的自动转换。也可以通过该类获得本地或远程主机所拥有的地址数量与地址信息。
*
* @short IPV4协议地址族。
*/
class __LGLIB__ lg_SocketAddress
{
public: // 公用数据
static const char ANYIP[]; /*!< 任意IP */
private: // 私有数据
typedef vector<string> StringVector;
typedef vector<in_addr> IPVector;
string m_szName; /*!< 机器名称 */
StringVector m_arrszAliases; /*!< 别名数组 */
IPVector m_arrIpAddress; /*!< IP地址数组 */
Port_t m_sPort; /*!< 网络字节顺序的端口号 */
public: // 构造/析构
/*!
* 构造函数。用现有的地址信息构造类,初始化个数据成员。
*
* @param addr 地址信息
*/
lg_SocketAddress( const sockaddr_in& addr );
/*!
* 明确构造函数,不能作为默认类型转换使用。通过明确给定各初始值,
* 构造类,初始化各数据成员。
*
* @param ip 地址字符串,可以是URL
* @param port 端口号
* @param dolookup 是否通过DNS服务器获得主机的详细信息
*/
explicit lg_SocketAddress( const string& ip = ANYIP,
Port_t port = 0,
bool dolookup = false );
/*!
*析构函数。
*/
virtual ~lg_SocketAddress( void );
public: // 运算符
/*!
* 类型转换运算符,可以将lg_SocketAddress类型转换为sockaddr_in类型。
*/
operator sockaddr_in() const;
/*!
* 赋值运算符,将sockaddr_in类型的数据赋值给这个类的各个成员。
*
* @param addr 源数据
* @return 用于a=b=c方式
*/
const sockaddr_in& operator=( const sockaddr_in& addr );
/*! 比较运算 */
bool operator==( const sockaddr_in& addr ) const;
public: // 方法
/*!
* 查询主机信息。通过DNS服务器查询主机信息,将个信息保存在相应的
* 私有数据成员中。
*/
void lookup( void );
void lookup( const string& ip );
/*!
* 获得主机名。一般需要调用Lookup方法才能获得正确的主机名信息。
*
* @return 主机名
*/
string getName( void ) const { return m_szName; }
public: // 属性
/*!
* 获得别名。根据所给索引,返回一个别名。注意,索引不能越界,可以通
* 过getNumAliases属性获得索引边界。一般需要调用Lookup方法才能获得
* 正确的别名信息。
*
* @param index 别名索引(一个主机可以拥有多个别名)
* @param 别名
*/
const string& getAliasName( uint32 index = 0 ) const;
/*!
* 获得IP地址的字符串形式。通过给定的索引获得IP地址的字符串信息。注意,
* 索引不能越界,可以通过getNumIp属性获得索引边界。一般需要调用Lookup
* 方法才能获得正确的地址信息。
*
* @param index 地址索引(一个主机可以帮定多了地址)
* @return 字符串形式的IP地址信息。
*/
string getIpString( uint32 index = 0 ) const;
/*!
* 获得别名的个数。一般需要调用Lookup方法才能获得正确的信息。
*
* @return 别名的个数
*/
int32 getNumAliases( void ) { return static_cast< int >( m_arrszAliases.size() ); }
/*!
* 获得IP地址数。一把需要调用Lookup方法才能获得正确的信息。
*
* @return ip地址数
*/
int32 getNumIp( void ) { return static_cast< int >( m_arrIpAddress.size() ); }
/*!
* 获得端口号
*
* @return 端口号
*/
Port_t getPort( void ) const;
private: // 私有过程
};
};
#endif
////////////////////////////////////////////CPP/////////////////////////////////////////
/* 版权所有 (C) 1997-2004
* 创建: 2004年10月20日
* 描述: TCP/IP协议地址族封装模块
*/
#include "StdAfx.h"
#include "lg_socketaddress.h"
#include "lg_Exception.h"
#pragma comment(lib, "ws2_32.lib")
# define herrno WSAGetLastError()
#include <string>
using namespace std;
namespace lglib {
static lg_SocketEnv __win32env;
//---------------------------------------------------------------------------
// 初始化常量成员
const char lg_SocketAddress::ANYIP[] = "0.0.0.0";
//---------------------------------------------------------------------------
// 构造函数
lg_SocketAddress::lg_SocketAddress( const sockaddr_in& addr )
{
m_arrIpAddress.push_back( addr.sin_addr );
m_sPort = addr.sin_port;
}
//---------------------------------------------------------------------------
// 明确构造函数
lg_SocketAddress::lg_SocketAddress( const string& ip,
Port_t port,
bool dolookup )
{
in_addr Address;
if ( dolookup )
{
lookup( ip );
}
else
{
//将IP地址数据转换为二进制
if ( ( Address.s_addr = inet_addr( ip.c_str() ) ) == INADDR_NONE )
{
//IP地址转换失败,可能是一个域名
lookup( ip );
}
else
{
m_arrIpAddress.push_back( Address );
}
}
this->m_sPort = htons( port );
}
//---------------------------------------------------------------------------
// 析构函数
lg_SocketAddress::~lg_SocketAddress( void )
{
}
//---------------------------------------------------------------------------
// 明确类型转换 sockaddr_in -> lg_SocketAddress
lg_SocketAddress::operator sockaddr_in() const
{
if ( m_arrIpAddress.empty() )
{
throw lg_Exception( "lg_SocketAddress::operator sockaddr_in::m_arrIpAddress.empty",
"IP地址不正确",
LG_SOCKETADDRESS_NO_IP_CODE );
}
sockaddr_in Address;
Address.sin_family = AF_INET;
Address.sin_port = m_sPort;
Address.sin_addr = m_arrIpAddress.front();
return Address;
}
//---------------------------------------------------------------------------
// 赋值运算 LG_SocketAddre = sockaddr_in
const sockaddr_in& lg_SocketAddress::operator=( const sockaddr_in& addr )
{
m_szName = "";
m_arrszAliases.clear();
m_arrIpAddress.clear();
m_arrIpAddress.push_back( addr.sin_addr );
m_sPort = addr.sin_port;
return addr;
}
//---------------------------------------------------------------------------
// 比较运算
bool lg_SocketAddress::operator==( const sockaddr_in& addr ) const
{
if ( addr.sin_port == m_sPort &&
addr.sin_addr.s_addr == m_arrIpAddress.front().s_addr )
{
return true;
}
return false;
}
//---------------------------------------------------------------------------
// 查询主机信息
void lg_SocketAddress::lookup( const string& ip )
{
hostent* hostinfo = NULL;
hostinfo = gethostbyname( ip.c_str() );
if ( hostinfo == NULL )
{
throw lg_Exception( "lg_SocketAddress::lookup( const string& ip )::gethostbyname", errno );
}
m_szName = hostinfo->h_name;
m_arrszAliases.clear();
// 保存所有发现的别名在列表中
if ( hostinfo->h_aliases[0] != NULL )
{
for ( char** alias=hostinfo->h_aliases; alias != NULL; alias++ )
{
m_arrszAliases.push_back( *alias );
}
}
m_arrIpAddress.clear();
// 保存所有发现的IP在列表中
for ( in_addr** addr = reinterpret_cast< in_addr** >( hostinfo->h_addr_list );
*addr != NULL;addr++ )
{
m_arrIpAddress.push_back( **addr );
}
}
//---------------------------------------------------------------------------
// 查询主机信息
void lg_SocketAddress::lookup( void )
{
hostent* hostinfo = NULL;
if ( m_arrIpAddress.empty() )
{
throw lg_Exception( "lg_SocketAddress::lookup( void )::gethostbyname",
"IP地址不正确",
LG_SOCKETADDRESS_NO_IP_CODE );
}
//只是使用列表中的第一个IP
hostinfo = gethostbyaddr( reinterpret_cast< char* >( &m_arrIpAddress.front() ),
sizeof( in_addr ),
AF_INET );
if ( hostinfo == NULL )
{
m_arrszAliases.clear();
m_szName = "";
return;
}
m_szName = hostinfo->h_name;
m_arrszAliases.clear();
//保存所有发现的别名在列表中
if ( hostinfo->h_aliases[0] != NULL )
{
try
{
for ( char** alias = hostinfo->h_aliases; alias != NULL; alias++ )
{
m_arrszAliases.push_back( *alias );
}
}
catch( ... )
{
}
}
m_arrIpAddress.clear();
//保存所有发现的IP在列表中
for ( in_addr** addr = reinterpret_cast< in_addr** >( hostinfo->h_addr_list );
*addr != NULL;addr++ )
{
m_arrIpAddress.push_back( **addr );
}
}
//---------------------------------------------------------------------------
// 获得别名
const string& lg_SocketAddress::getAliasName( uint32 index ) const
{
if ( index >= m_arrszAliases.size() || index < 0 )
{
throw lg_Exception( "lg_SocketAddress::getAliasName",
"索引越界!",
LG_SOCKETADDRESS_OFF_RANGE_CODE );
}
return m_arrszAliases[index];
}
//---------------------------------------------------------------------------
// 获得IP地址字符串信息
string lg_SocketAddress::getIpString( uint32 index ) const
{
if ( index >= m_arrIpAddress.size() || index < 0 )
{
throw lg_Exception( "lg_SocketAddress::getIpString",
"索引越界!",
LG_SOCKETADDRESS_OFF_RANGE_CODE );
}
string ip = inet_ntoa( m_arrIpAddress[index] );
return ip;
}
//--------------------------------------------------------------------------
Port_t lg_SocketAddress::getPort( void ) const
{
return ntohs( m_sPort );
}
};