IP
層的封裝
C++
通用框架的設(shè)計(jì)
作者:
naven
1??????????
IP
層封裝介紹
TCP/UDP
是網(wǎng)絡(luò)編程的基礎(chǔ)技術(shù),分別代表面向連接的穩(wěn)定的網(wǎng)絡(luò)通信技術(shù)和非連接方式的廣播形式的網(wǎng)絡(luò)通信技術(shù),它們都建立在
IP
層之上,所以
IP
層的封裝尤為重要。
IP
層的封裝接口主要包括
DNS
的查詢、
IP
地址和域名的互查、本地
IP
及名字的查詢等,目前
IP
層使用的主要實(shí)現(xiàn)技術(shù)是
IPv4
,但是未來(lái)會(huì)慢慢升級(jí)到容量更大的
IPv6
,所以
IP
層的封裝需要要同時(shí)支持這兩種協(xié)議。操作系統(tǒng)實(shí)現(xiàn)它們都是通過(guò)增加新的
API
以及新的地址結(jié)構(gòu)實(shí)現(xiàn)的,開發(fā)者編寫跨協(xié)議的網(wǎng)絡(luò)應(yīng)用需要編寫較復(fù)雜的程序來(lái)區(qū)分
IPv4
和
IPv6
協(xié)議,優(yōu)秀的
ACE
框架則通過(guò)條件編譯來(lái)支持
IPv6
,好像不能同時(shí)在程序中使用
IPv4
和
IPv6
協(xié)議。本
C++
框架參考
Java
的
InetAddress
及相關(guān)類實(shí)現(xiàn)了類似跨協(xié)議的
IP
層封裝,編寫網(wǎng)絡(luò)應(yīng)用基本不用考慮兩種協(xié)議的不同,應(yīng)為它們對(duì)外的接口類都是
InetAddress
,另外同時(shí)提供了與
Java
一樣簡(jiǎn)單的域名和
IP
地址互查的接口,使用非常容易。
?
主要有如下一些類
?
class AbstraceInetAddress ???????????????????????? IP
地址的抽象類,定義
IP
類的方法
class InetAddress??????????????????????????????????????????
表示
IP
地址的接口類
class Inet4Address?? ?????????????????? ????????
表示
IPv4
協(xié)議的
IP
地址實(shí)現(xiàn)類
class Inet6Address?? ?????????????????? ????????
表示
IPv6
協(xié)議的
IP
地址實(shí)現(xiàn)類
class SocketAddress?????????????????? ???????????????????????????
表示以域名
/IP/PORT
標(biāo)識(shí)的網(wǎng)絡(luò)地址
Abstract
類
class InetSocketAddress????????????????????
表示以域名
/IP/PORT
標(biāo)識(shí)的網(wǎng)絡(luò)地址實(shí)現(xiàn)類
???????? class NameService?????????????????????????????????????????
內(nèi)部使用的訪問(wèn)域名服務(wù)的類
?
對(duì)于
IP
尋址,有如下幾個(gè)類:
InetAddress
、
Inet4Address
和
Inet6Address
。
IPv4
的實(shí)現(xiàn)類
Inet4AddressImpl
使用一個(gè)
32
位的
unsignednumber
標(biāo)識(shí),一個(gè)
IPv4
地址形式為
nnn.nnn.nnn.nnn
,其中
n
為一個(gè)整數(shù),例于
129.250.35.250
。而
IPv6
的實(shí)現(xiàn)類
Inet6AddressImpl
使用一個(gè)
128
位的
unsigned number
標(biāo)識(shí),形式如同
x:x:x:x:x:x:x:x
,其中
x
表示一個(gè)十六進(jìn)制的數(shù)字,例于
1080:0:0:0:8:800:200C:417A
。
?
對(duì)于
Socket
尋址,有如下兩個(gè)類:
SocketAddress
和
InetSocketAddress
。其中
SocketAddress
是一個(gè)
abstract
的
socket
地址,不依賴于一個(gè)特定的協(xié)議,它提供給實(shí)現(xiàn)特定協(xié)議的子類來(lái)使用。
InetSocketAddress
是
SocketAddress
的一個(gè)子類,它表示一個(gè)
IP
類的
socket
地址,包括一個(gè)
IP
地址(如
129.250.35.250
)和端口(如
80
),或者包括一個(gè)域名(如
coastnews.com
)和一個(gè)端口(如
1000
),或者僅僅包括一個(gè)端口(如
1010
)。
2??????????
Hello World!
下面的程序示例如何用上面的類進(jìn)行
IP
查詢操作:
?
void
?main()?

{
????
//
?定義IP地址數(shù)組以存儲(chǔ)IP地址列表
????InetAddressArray?iaa;?
????
//
?調(diào)用InetAddress方法獲取此域名的所有IP,并存放到數(shù)組iaa中
????
int
?cnt?
=
?InetAddress::getAllByName(
"
www.google.com
"
,?iaa);?
????
????
//
?定義數(shù)組的迭代器
????InetAddressArray::iterator?it(iaa);?
????
//
?遍歷數(shù)組,列出所有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
類
此類定義一個(gè)
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
類
此類實(shí)現(xiàn)一個(gè)
Internet Procotol
(
IP
)地址,一個(gè)
IP
地址即可以是用一個(gè)
32-bit
的
unsigned
數(shù)來(lái)表示,也可以用一個(gè)
128-bit
的
unsgined
數(shù)來(lái)表示,它內(nèi)部實(shí)現(xiàn)了一個(gè)底層的協(xié)議如
UDP
和
TCP
協(xié)議。
IP
地址的結(jié)構(gòu)定義在
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
。一個(gè)
InetAddress
的實(shí)體由一個(gè)
IP
地址和一個(gè)可能它通訊的
host name
組成,這個(gè)
host name
依賴于它是否使用一個(gè)
host name
來(lái)構(gòu)造,或者它是否已經(jīng)做了
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
類
這個(gè)類實(shí)現(xiàn)一個(gè)名字服務(wù)的接口供
InetAddress
查詢
IP
及其協(xié)議類型使用,它有如下一些方法:
?
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
類
這個(gè)類實(shí)現(xiàn)一個(gè)
Internet Protocol version 4 (IPv4)
協(xié)議地址,定義在:
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
。一個(gè)
IPv4
地址的文本表示法使用如下一個(gè)格式輸入:
?
d.d.d.d
d.d.d
d.d
d
?
當(dāng)四個(gè)部分都被指定后,每一個(gè)會(huì)被解釋為一個(gè)
assigned
字節(jié)的數(shù)據(jù),從左到右,附值給一個(gè)四個(gè)字節(jié)的
IPv4
地址。此類的定義如下:
?
class
?Inet4Adress?:?
public
?AbstractInetAddress

{

????
/**/
/*
*
?????*?Holds?a?32-bit?IPv4?address.
?????*
?????*?@serial
?????
*/
????
int
?_address;

}
;
?
7??????????
Inet6Adress
類
這個(gè)類實(shí)現(xiàn)一個(gè)
Internet Protocol version 6 (IPv6)
協(xié)議地址,定義在:
RFC2373 IP Version 6 Addressing Architecture
:
http://www.ietf.org/rfc/rfc2373.txt
。一個(gè)
IPv6
地址的文本表示法使用如下一個(gè)格式輸入:
首選的格式是
x:x:x:x:x:x:x:x
,其中所有的“
x
”是表示地址的
8
個(gè)
16-bit
塊的
16
進(jìn)制數(shù)值,這是一個(gè)完整的格式,舉例如下:
?
1080:0:0:0:8:800:200C:417A
?
需要注意的是以
0
開始的欄位是無(wú)必要寫的,然而在每個(gè)欄位中必需有一個(gè)數(shù)字,除了如下描述的情形外:
由于一些分配了確定類型的
IPv6
地址的方法,它將為地址容納一個(gè)長(zhǎng)的
zero bit
的
strings
所共有,為了使得寫這些包含了
zero bit
的地址更容易,所以使用
“
::
”來(lái)表示多個(gè)連續(xù)為
0
的欄位組,而“
::
”在一個(gè)地址中只能出現(xiàn)一次,“
::
”還能被用來(lái)壓縮一個(gè)地址中以
0
開始到
0
結(jié)尾的欄位組,例如:
?
1080::8:800:200C:417A
?
一種可替換的格式在有時(shí)候更為便利,但處理混合有
IPv4
和
IPv6
協(xié)議的節(jié)點(diǎn)如
x:x:x:x:x:x:d.d.d.d
,其中所有的“
x
”表示地址的
6
個(gè)
high-order 16-bit
部分的十六進(jìn)制數(shù),而其它的“
d
”表示標(biāo)準(zhǔn)的
IPv4
地址的
4
個(gè)
low-order 8-bit
部分的十進(jìn)制數(shù),例如:
?
::FFFF:129.144.52.38
::129.144.52.38
?
其中“
::FFFF:d.d.d.d
”和“
::d.d.d.d
”分別地表示一個(gè)
IPv4-mapped IPv6
地址和一個(gè)
IPv4-compatible IPv6
地址,需要注意的是
IPv4
部分必須是
“
d.d.d.d
”格式,以下的格式都是不正確的:
?
::FFFF:d.d.d
::FFFF:d.d
::d.d.d
::d.d
?
但是下面的格式卻是合法的:
?
::FFFF:d
?
然而它是一個(gè)表示
IPv4-compatible IPv6
地址的非傳統(tǒng)的表示格式,
?
::255.255.0.d
?
其中的“
::d
”符合一個(gè)通常的
IPv6
地址,如
?
0:0:0:0:0:0:0:d
?
對(duì)于一個(gè)需要返回文本格式的地址的方法,
Inet6Address
將返回完整的格式,因?yàn)樗欠浅C鞔_的,當(dāng)在與其他文本數(shù)據(jù)結(jié)合使用的時(shí)候。
?
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
類實(shí)現(xiàn)了一個(gè)不與任何一種協(xié)議綁定的
Socket
地址,它是一個(gè)抽象類,這表明必須使用它的綁定了特定協(xié)議的子類來(lái)表示
Socket
地址的實(shí)現(xiàn)。它為
sockets
的
binding
和
connecting
或者
return values
提供一個(gè)不可變的對(duì)象。
InetSocketAddress
類實(shí)現(xiàn)了一個(gè)
IP Socket Address
(即一個(gè)
IP address
加一個(gè)
port
端口),它還能是一對(duì)
host name
加一個(gè)
port
端口,此時(shí)會(huì)嘗試去查找確定
host name
的實(shí)際地址。它的定義如下所示:
?
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++
通用框架的設(shè)計(jì)
作者:
naven
日期:
2006-3-19