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