一 点睛
SocketAddr类定义在lib/SocketAddr.hpp中,实现在lib/SocketAddr.cpp中。
SocketAddr类封装了网络通信中经常用到的地址结构以及在这些结构上进行的操作。
地址解析也是在SocketAddr的成员函数中完成的。
sockaddr用来表示网络地址中的通用数据结构。
sockaddr_in用来表示TCP/IP地址的数据结构。
两个结构可以相互转换,它们表示同一地址。它们在内存中对应的区域是重合的。
二 类定义
// 该成员函数都是对mAddress进行读取或修改的操作
class SocketAddr {
public:
SocketAddr( const char* inHostname = NULL, unsigned short inPort = 0, bool isIPv6 = false );
SocketAddr( const struct sockaddr* inAddr, Socklen_t inSize );
~SocketAddr();
void setHostname( const char* inHostname ); // DNS lookup
void getHostname( char* outHostname, size_t len ); // reverse DNS lookup
void getHostAddress( char* outAddress, size_t len ); // dotted decimal
void setPort( unsigned short inPort );
void setPortAny( void );
unsigned short getPort( void );
void setAddressAny( void );
// return pointer to the struct sockaddr
struct sockaddr* get_sockaddr( void );
// return pointer to the struct sockaddr_in (IPv4)
struct sockaddr_in* get_sockaddr_in( void );
// return pointer to the struct in_addr
struct in_addr* get_in_addr( void );
#ifdef IPV6
// return pointer to the struct in_addr
struct in6_addr* get_in6_addr( void );
#endif
// return the sizeof the addess structure (struct sockaddr_in)
Socklen_t get_sizeof_sockaddr( void );
bool isMulticast( void );
bool isIPv6(void) {
return mIsIPv6;
};
static bool are_Equal(sockaddr *first, sockaddr *second);
static bool Hostare_Equal(sockaddr *first, sockaddr *second);
static Socklen_t mAddress_size;
protected:
void zeroAddress( void );
// iperf_sockaddr实际上是sockaddr_in
iperf_sockaddr mAddress;
bool mIsIPv6;
};
三 类实现
类的成员函数都是对mAddress进行读取或修改的操作,比较复杂的成员函数是setHostname,它完成了地址解析的过程,删减后的源代码如下
void SocketAddr::setHostname( const char* inHostname ) {
assert( inHostname != NULL );
mIsIPv6 = false;
mAddress.sin_family = AF_INET;
// inet_pton是一个IP地址转换函数,可以在将IP地址在“点分十进制”和“二进制整数”之间转换
// 因为在window中 gethostbyname 不理解点分十进制
int rc = inet_pton( AF_INET, inHostname, (unsigned char*)&(mAddress.sin_addr) );
if ( rc == 0 ) {
// gethostbyname()返回对应于给定主机名的包含主机名字和地址信息的hostent结构的指针。
struct hostent *hostP = gethostbyname( inHostname );
if ( hostP == NULL ) {
/* this is the same as herror() but works on more systems */
const char* format;
switch ( h_errno ) {
case HOST_NOT_FOUND:
format = "%s: Unknown host\n";
break;
case NO_ADDRESS:
format = "%s: No address associated with name\n";
break;
case NO_RECOVERY:
format = "%s: Unknown server error\n";
break;
case TRY_AGAIN:
format = "%s: Host name lookup failure\n";
break;
default:
format = "%s: Unknown resolver error\n";
break;
}
fprintf( stderr, format, inHostname );
exit(1);
return; // TODO throw
}
memcpy(&(mAddress.sin_addr), *(hostP->h_addr_list),
(hostP->h_length));
}
#endif
}