Javen-Studio 咖啡小屋

http://javenstudio.org - C++ Java 分布式 搜索引擎
Naven's Research Laboratory - Thinking of Life, Imagination of Future

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  24 随笔 :: 57 文章 :: 170 评论 :: 4 Trackbacks

IP 层的封装

C++ 通用框架的设计 作者: naven

1           IP 层封装介绍

TCP/UDP 是网络编程的基础技术,分别代表面向连接的稳定的网络通信技术和非连接方式的广播形式的网络通信技术,它们都建立在 IP 层之上,所以 IP 层的封装尤为重要。 IP 层的封装接口主要包括 DNS 的查询、 IP 地址和域名的互查、本地 IP 及名字的查询等,目前 IP 层使用的主要实现技术是 IPv4 ,但是未来会慢慢升级到容量更大的 IPv6 ,所以 IP 层的封装需要要同时支持这两种协议。操作系统实现它们都是通过增加新的 API 以及新的地址结构实现的,开发者编写跨协议的网络应用需要编写较复杂的程序来区分 IPv4 IPv6 协议,优秀的 ACE 框架则通过条件编译来支持 IPv6 ,好像不能同时在程序中使用 IPv4 IPv6 协议。本 C++ 框架参考 Java InetAddress 及相关类实现了类似跨协议的 IP 层封装,编写网络应用基本不用考虑两种协议的不同,应为它们对外的接口类都是 InetAddress ,另外同时提供了与 Java 一样简单的域名和 IP 地址互查的接口,使用非常容易。

 

主要有如下一些类

 

class AbstraceInetAddress                          IP 地址的抽象类,定义 IP 类的方法

class InetAddress                                           表示 IP 地址的接口类

class Inet4Address                               表示 IPv4 协议的 IP 地址实现类

class Inet6Address                               表示 IPv6 协议的 IP 地址实现类

class SocketAddress                                               表示以域名 /IP/PORT 标识的网络地址 Abstract

class InetSocketAddress                     表示以域名 /IP/PORT 标识的网络地址实现类

         class NameService                                          内部使用的访问域名服务的类

 

对于 IP 寻址,有如下几个类: InetAddress Inet4Address Inet6Address IPv4 的实现类 Inet4AddressImpl 使用一个 32 位的 unsignednumber 标识,一个 IPv4 地址形式为 nnn.nnn.nnn.nnn ,其中 n 为一个整数,例于 129.250.35.250 。而 IPv6 的实现类 Inet6AddressImpl 使用一个 128 位的 unsigned number 标识,形式如同 x:x:x:x:x:x:x:x ,其中 x 表示一个十六进制的数字,例于 1080:0:0:0:8:800:200C:417A

 

对于 Socket 寻址,有如下两个类: SocketAddress InetSocketAddress 。其中 SocketAddress 是一个 abstract socket 地址,不依赖于一个特定的协议,它提供给实现特定协议的子类来使用。 InetSocketAddress SocketAddress 的一个子类,它表示一个 IP 类的 socket 地址,包括一个 IP 地址(如 129.250.35.250 )和端口(如 80 ),或者包括一个域名(如 coastnews.com )和一个端口(如 1000 ),或者仅仅包括一个端口(如 1010 )。

2           Hello World!

下面的程序示例如何用上面的类进行 IP 查询操作:

 

void  main() 
{
    
//  定义IP地址数组以存储IP地址列表
    InetAddressArray iaa; 
    
//  调用InetAddress方法获取此域名的所有IP,并存放到数组iaa中
     int  cnt  =  InetAddress::getAllByName( " www.google.com " , iaa); 
    
    
//  定义数组的迭代器
    InetAddressArray::iterator it(iaa); 
    
//  遍历数组,列出所有IP地址
     while ! it.done() )  {
        
//  输出IP地址的字符串形式
        printf( " %s\n " , it -> getHostAddress().c_str()); 
        
//  迭代器向前移一位
        it.advance(); 
    }

}

 

程序输出如下:

 

66.102.7.99

66.102.7.104

66.102.7.147

 

3           AbstractInetAddress

此类定义一个 Internet Procotol IP )地址类的接口,类定义如下:

 

 

class  AbstractInetAddress 
{

protected
    
/*
     * Specify the address family: Internet Protocol, Version 4
     * @since 1.4
     
*/

    
const   static   int  IPv4  =  INET_FAMILY_IPV4;

    
/*
     * Specify the address family: Internet Protocol, Version 6
     * @since 1.4
     
*/

    
const   static   int  IPv6  =  INET_FAMILY_IPV6;

    
/*
     * Specify address family preference 
     
*/

    
static  BOOL preferIPv6Address; 
    
    
/*
     * Used to store the name service provider 
     
*/

    
static  NameService  & nameService; 

    
/*
     * Used to pointer to the actual address implemented 
     
*/

    
static  InetAddressImplAutoPtr _impl; 

    
virtual  InetAddressAutoPtr clone()  =   0

public
    
/* *
     * Destructor must implemented. 
     
*/

    
virtual   ~ AbstractInetAddress()  {}  

    
/* *
     * Utility routine to check this InetAddress. 
     
*/

    
virtual  BOOL isMulticastAddress()  =   0
    
virtual  BOOL isAnyLocalAddress()  =   0
    
virtual  BOOL isLoopbackAddress()  =   0
    
virtual  BOOL isLinkLocalAddress()  =   0
    
virtual  BOOL isSiteLocalAddress()  =   0
    
virtual  BOOL isMCGlobal()  =   0
    
virtual  BOOL isMCNodeLocal()  =   0
    
virtual  BOOL isMCLinkLocal()  =   0
    
virtual  BOOL isMCSiteLocal()  =   0
    
virtual  BOOL isMCOrgLocal()  =   0

    
virtual  SockAddr getAddress()  =   0
    
virtual  String getHostAddress()  =   0
    
virtual  BOOL isUnresolved()  =   0

    
/* *
     * Compares this object against the specified object.
     * The result is <code>true</code> if and only if the argument is
     * not <code>null</code> and it represents the same IP address as
     * this object.
     * <p>
     * Two instances of <code>InetAddress</code> represent the same IP
     * address if the length of the byte arrays returned by
     * <code>getAddress</code> is the same for both, and each of the
     * array components is the same for the byte arrays.
     *
     * @param   obj   the object to compare against.
     * @return  <code>true</code> if the objects are the same;
     *          <code>false</code> otherwise.
     
*/

    BOOL equals(AbstractInetAddress 
& addr) 
    
{
        
return  getAddress()  ==  addr.getAddress()  ?  TRUE : FALSE; 
    }


}
;

 

4           InetAddress

此类实现一个 Internet Procotol IP )地址,一个 IP 地址即可以是用一个 32-bit unsigned 数来表示,也可以用一个 128-bit unsgined 数来表示,它内部实现了一个底层的协议如 UDP TCP 协议。 IP 地址的结构定义在 RFC790 Assigned Numbers http://www.ietf.org/rfc/rfc790.txt RFC1918 Address Allocation for Private Internets http://www.ietf.org/rfc/rfc1918.txt RFC2365 Administratively Scoped IP Multicast http://www.ietf.org/rfc/rfc2365.txt RFC2373 Version 6 Addressing Architecture http://www.ietf.org/rfc/rfc2373.txt 。一个 InetAddress 的实体由一个 IP 地址和一个可能它通讯的 host name 组成,这个 host name 依赖于它是否使用一个 host name 来构造,或者它是否已经做了 host name 决议的倒装( reverse host name resolution )。

InetAddress 类的定义如下:

 

class  InetAdress :  public  AbstractInetAddress
{
    
/* *
     * @serial
     
*/

    String _hostName; 

    
/* *
     * Specifies the address family type, for instance, '1' for IPv4
     * addresses, and '2' for IPv6 addresses.
     *
     * @serial
     
*/

    
int  _family; 

    
/*
     * Used to store the best available hostname 
     
*/

    String _canonicalHostName; 

    
/*
     * Used to pointer to the actual address object 
     
*/

    InetAddressAutoPtr _ia;
}
;

 

 

5           NameService

这个类实现一个名字服务的接口供 InetAddress 查询 IP 及其协议类型使用,它有如下一些方法:

 

class  NameService
{
    
/* *
     * The gethostbyaddr function retrieves the host information 
     * corresponding to a network address.
     * 
     * Note  The gethostbyaddr function has been deprecated by the 
     * introduction of the getnameinfo function. Developers creating 
     * socket applications are urged to use the getnameinfo function 
     * instead of the gethostbyaddr function. See Remarks.
     
*/

    
int  getHostByAddr(SockAddr  & addr, String  & host); 

    
/* *
     * Lookup hostname in name service. If
     * found return address and return count, -1 if not found. 
     *
     * @param host  host name to lookup 
     * @param addrs return the address list that found 
     * @return found addresses count, -1 if not found or error. 
     
*/

    
int  lookupAllHostAddr( const  String  & host, InetAddressArray  & addrs); 

    
/* *
     * Lookup host port with service name and protocol in name service. If
     * found return port and return count, -1 if not found. 
     *
     * @param service  host service to lookup 
     * @param protocol service protocol, default is "TCP"  
     * @return host port, -1 if not found or error. 
     
*/

    
int  lookupHostPort( const  String  & service,  const  String  & protocol  =   " TCP " );
}
;

 

 

6           Inet4Adress

这个类实现一个 Internet Protocol version 4 (IPv4) 协议地址,定义在: RFC790 Assigned Numbers http://www.ietf.org/rfc/rfc790.txt RFC1918 Address Allocation for Private Internets http://www.ietf.org/rfc/rfc1918.txt RFC2365 Administratively Scoped IP Multicast http://www.ietf.org/rfc/rfc2365.txt 。一个 IPv4 地址的文本表示法使用如下一个格式输入:

 

d.d.d.d

d.d.d

d.d

d

 

当四个部分都被指定后,每一个会被解释为一个 assigned 字节的数据,从左到右,附值给一个四个字节的 IPv4 地址。此类的定义如下:

 

class  Inet4Adress :  public  AbstractInetAddress
{
    
/* *
     * Holds a 32-bit IPv4 address.
     *
     * @serial
     
*/

    
int  _address;

}
;

 

7           Inet6Adress

这个类实现一个 Internet Protocol version 6 (IPv6) 协议地址,定义在: RFC2373 IP Version 6 Addressing Architecture http://www.ietf.org/rfc/rfc2373.txt 。一个 IPv6 地址的文本表示法使用如下一个格式输入:

首选的格式是 x:x:x:x:x:x:x:x ,其中所有的“ x ”是表示地址的 8 16-bit 块的 16 进制数值,这是一个完整的格式,举例如下:

 

1080:0:0:0:8:800:200C:417A

 

需要注意的是以 0 开始的栏位是无必要写的,然而在每个栏位中必需有一个数字,除了如下描述的情形外:

由于一些分配了确定类型的 IPv6 地址的方法,它将为地址容纳一个长的 zero bit strings 所共有,为了使得写这些包含了 zero bit 的地址更容易,所以使用 :: ”来表示多个连续为 0 的栏位组,而“ :: ”在一个地址中只能出现一次,“ :: ”还能被用来压缩一个地址中以 0 开始到 0 结尾的栏位组,例如:

 

1080::8:800:200C:417A

 

一种可替换的格式在有时候更为便利,但处理混合有 IPv4 IPv6 协议的节点如 x:x:x:x:x:x:d.d.d.d ,其中所有的“ x ”表示地址的 6 high-order 16-bit 部分的十六进制数,而其它的“ d ”表示标准的 IPv4 地址的 4 low-order 8-bit 部分的十进制数,例如:

 

::FFFF:129.144.52.38

::129.144.52.38

 

其中“ ::FFFF:d.d.d.d ”和“ ::d.d.d.d ”分别地表示一个 IPv4-mapped IPv6 地址和一个 IPv4-compatible IPv6 地址,需要注意的是 IPv4 部分必须是 d.d.d.d ”格式,以下的格式都是不正确的:

 

::FFFF:d.d.d

::FFFF:d.d

::d.d.d

::d.d

 

但是下面的格式却是合法的:

 

::FFFF:d

 

然而它是一个表示 IPv4-compatible IPv6 地址的非传统的表示格式,

 

::255.255.0.d

 

其中的“ ::d ”符合一个通常的 IPv6 地址,如

 

0:0:0:0:0:0:0:d

 

对于一个需要返回文本格式的地址的方法, Inet6Address 将返回完整的格式,因为它是非常明确的,当在与其他文本数据结合使用的时候。

 

Inet6Address 类定义如下:

 

class  Inet6Adress :  public  AbstractInetAddress
{
    
/*
     * cached scope_id - for link-local address use only.
     
*/

    
int  _cached_scope_id; 

    
/* *
     * Holds a 128-bit (16 bytes) IPv6 address.
     *
     
*/

    
int  _ipaddress[ 16 ];
}
;

 

 

8           SocketAddress 类和 InetSocketAddress

SocketAddress 类实现了一个不与任何一种协议绑定的 Socket 地址,它是一个抽象类,这表明必须使用它的绑定了特定协议的子类来表示 Socket 地址的实现。它为 sockets binding connecting 或者 return values 提供一个不可变的对象。

InetSocketAddress 类实现了一个 IP Socket Address (即一个 IP address 加一个 port 端口),它还能是一对 host name 加一个 port 端口,此时会尝试去查找确定 host name 的实际地址。它的定义如下所示:

 

class  InetSocketAddress :  public  SocketAddress 
{
    
/* *
     * The hostname of the Socket Address
     * @serial
     
*/
     
    String _hostname; 
    
    
/*
     * The IP address of the Socket Address
     * @serial
     
*/

    InetAddress _addr; 
    
    
/* *
     * The port number of the Socket Address
     * @serial
     
*/
   
    
int  _port;
}
;

 

 

 

C++ 通用框架的设计 作者: naven 日期: 2006-3-19

posted on 2006-03-19 12:54 Javen-Studio 阅读(2886) 评论(4)  编辑 收藏 引用

评论

# re: IP层的封装(Java的InetAddress类的C++实现) 2006-03-19 22:55 fiestay
看样子还不错,能否提供实现代码?  回复  更多评论
  

# re: IP层的封装(Java的InetAddress类的C++实现) 2006-04-17 10:54 Javen-Studio
等我有时间我先发布一个库给大家试用看看,谢谢支持!  回复  更多评论
  

# re: IP层的封装(Java的InetAddress类的C++实现) 2006-06-29 21:22 scott
please show us the missing source code. thnx  回复  更多评论
  

# re: IP层的封装(Java的InetAddress类的C++实现) 2006-06-30 09:37 Javen-Studio
快了,我会发布一个windows下的试用版本
  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理