




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、第五章 名字與地址轉(zhuǎn)換5.1 域名系統(tǒng)盡管通過IP地址可以唯一地識別主機(jī)上的網(wǎng)絡(luò)接口,從而訪問網(wǎng)絡(luò)中的每個主機(jī)。但是,由于IP地址不便于人們記憶,因此人們還是習(xí)慣于使用主機(jī)名來訪問網(wǎng)絡(luò)。隨著IPv6協(xié)議的不斷廣泛應(yīng)用,數(shù)值地址變得更長,手工鍵入一個地址更容易出錯。在大多數(shù)操作系統(tǒng)中,任何應(yīng)用程序都可以調(diào)用一個標(biāo)準(zhǔn)的庫函數(shù)來查看給定名字的主機(jī)的IP地址(UNIX系統(tǒng)中函數(shù)名);同樣,系統(tǒng)還提供了一個逆函數(shù),即給定主機(jī)的IP地址,查看它所對應(yīng)的主機(jī)名。大多數(shù)使用主機(jī)名作為參數(shù)的應(yīng)用程序也支持把IP地址作為參數(shù)。域名系統(tǒng)DNS(Domain Name System)主要用于主機(jī)名與IP地址間的映射。
2、主機(jī)名可以是簡單名字,例如Jida,也可以是全限定域名FQDN(Fully Qualified Domain Name),例如。嚴(yán)格地說,F(xiàn)QDN也稱為絕對名字(absolute name),因此必須以一個點(diǎn)號結(jié)尾,但用戶經(jīng)常省略最后的點(diǎn)號。在Internet上使用了基于層次型的名字管理機(jī)制。在Internet的層次型名字管理中,先由中央管理機(jī)構(gòu)(例如Internet的NIC)將最高一級的名字空間進(jìn)行劃分,并將相應(yīng)部分的管理權(quán)交給相應(yīng)的機(jī)構(gòu),各管理機(jī)構(gòu)可對名字空間進(jìn)行進(jìn)一步的劃分。一般來說,最高一級的名字空間的劃分是基于“網(wǎng)絡(luò)節(jié)點(diǎn)名”(site name)的。網(wǎng)絡(luò)節(jié)點(diǎn)的概念是對Internet
3、整個網(wǎng)絡(luò)的一部分(通常由若干個網(wǎng)絡(luò)構(gòu)成)的一種抽象,這些網(wǎng)絡(luò)的組織關(guān)系或地理位置聯(lián)系非常緊密,可以將它們看成一個節(jié)點(diǎn)。各個網(wǎng)絡(luò)節(jié)點(diǎn)中又可劃分成不同的管理組。組名下面是主機(jī)的本地名。典型的Internet層次型主機(jī)名由三部分構(gòu)成:本地名稱.管理組名.網(wǎng)絡(luò)節(jié)點(diǎn)名例如,其中cn屬于第一級的名字空間,代表國家;第二級域為,代表教育機(jī)構(gòu),最低一級代表吉林大學(xué)。5.1.1 資源記錄在TCP/IP環(huán)境中,域名系統(tǒng)(DNS)是一個分布式數(shù)據(jù)庫系統(tǒng),通過它來提供IP地址和主機(jī)名之間的映射。DNS中的條目稱為資源記錄RR(resource record),僅有少數(shù)幾類RR會影響名字與地址轉(zhuǎn)換。AA記錄將主機(jī)名映射
4、為32位的IPv4地址。例如,這里有域中關(guān)于主機(jī)solaris的四個DNS記錄,其中第一個就是一個A記錄:IN AAAA5f1b:df00:ce3e:e200:0020:0800:2078:e3e3IN MX5 .IN MX10 .AAAAAAAA記錄將主機(jī)名映射為128位的IPv6地址。PTRPTR記錄(稱為“指針記錄”)將IP地址映射為主機(jī)名。對于IPv4地址,32位地址的四個字節(jié)順序反轉(zhuǎn),每個字節(jié)都轉(zhuǎn)換成它的十進(jìn)制ASCII值(0到255),然后附上,結(jié)果串用于PTR查詢。對于IPv6地址,128位地址中的32個4位組順序反轉(zhuǎn),每組被轉(zhuǎn)換成相應(yīng)的十六進(jìn)制ASCII
5、值(0到9,a到f),并附上.例如,主機(jī)solaris的兩個PTR記錄為:06.和3.。MXMX記錄指定一個主機(jī)作為某主機(jī)的“郵件交換器”。在上面主機(jī)的solaris例子中,提供了兩個MX記錄,第一個記錄的優(yōu)先級是5,第二個記錄的優(yōu)先級是10,當(dāng)有多個MX記錄存在時,需按優(yōu)先級值的順序使用,從最小值開始。CNAMECNAME代表“canonical name(規(guī)范名字)”,其常見的用法是為常用服務(wù)如
6、WWW和FTP指派一個CNAME記錄。如果用戶使用這些服務(wù)名而不是實際上的主機(jī)名,則它在服務(wù)挪到其它主機(jī)上時是透明的。例如,主機(jī)Jida的CNAME如下:5.1.2 解析器和名字服務(wù)器組織運(yùn)行一個或多個名字服務(wù)器(name server),它們通常就是所說的BIND(Berkeley Internet Name Domain)程序。任何應(yīng)用程序,通過調(diào)用稱為解析器(resolver)的庫中的函數(shù)來與DNS服務(wù)器聯(lián)系。應(yīng)用程序用來將主機(jī)名轉(zhuǎn)換為IP地址或進(jìn)行相反過程的一組函數(shù)稱為解析器。最常見的解析器函數(shù)是gethostbyname和gethostbyaddr,前者將主機(jī)名映射為IP地址,后者執(zhí)
7、行相反的映射。圖5-1說明了應(yīng)用進(jìn)程、解析器和名字服務(wù)器的典型關(guān)系。解析器代碼包含在系統(tǒng)庫中,在構(gòu)造應(yīng)用程序時被鏈接到應(yīng)用程序中。應(yīng)用程序代碼使用正常的函數(shù)調(diào)用來調(diào)用解析器代碼,最典型的就是調(diào)用函數(shù)gethostbyname和gethostbyaddr。應(yīng)用進(jìn)程應(yīng)用程序代碼函數(shù)返回函數(shù)調(diào)用UDP請求遠(yuǎn)程名字服務(wù)器本地名字服務(wù)器解析器代碼UDP應(yīng)答解析器配置文件圖5-1 應(yīng)用進(jìn)程、解析器和名字服務(wù)器的關(guān)系解析器代碼讀其依賴于系統(tǒng)的配置文件來確定組織的名字服務(wù)器們的所在位置。文件/etc/resolv.conf一般包含本地名字服務(wù)器的IP地址。解析器使用UDP給本地名字服務(wù)器發(fā)查詢,如果本地名字服
8、務(wù)器不知道答案,它也可以使用UDP在整個因特網(wǎng)上給其它名字服務(wù)器發(fā)查詢。5.1.3 DNS替代方法不使用DNS也可以得到主機(jī)的名字和地址信息,最常用的替代方法為靜態(tài)主機(jī)文件(一般為文件/etc/hosts)或網(wǎng)絡(luò)信息系統(tǒng)NIS(Network Information System)。這里需要注意的是,管理員如何配置一個主機(jī)來使用不同的名字服務(wù)是依賴于不同的實現(xiàn)的,Solaris2.x和HP-UX10.30使用/etc.nsswitch.conf,Digital Unix使用文件/etc/svc.conf,,IBM AIX使用文件/etc/netsvc.conf。BIND8.1提供了自己的名字為
9、信息檢索服務(wù)IRS(Information Retrival Service)的版本,它使用文件/etc/irs.conf。如果一個名字服務(wù)器將為主機(jī)名查找所用,則所有這些系統(tǒng)都使用文件/etc/resolv.conf來指定此名字服務(wù)器的IP地址。這些差異一般對應(yīng)用程序開發(fā)人員透明,因此,用戶只需調(diào)用gethostbyname和gethostbyaddr這樣的解析器函數(shù)就可以了。5.2 gethostbyname函數(shù)計算機(jī)主機(jī)通常以人們可讀的名字被認(rèn)知,尤其是從IPv4協(xié)議向IPv6協(xié)議移植時,由于IPv6地址比IPv4地址要長得多,使用名字服務(wù)顯得更加正確和重要。查找主機(jī)名最基本的函數(shù)是ge
10、thostbyname,如果調(diào)用成功,它返回一個指向結(jié)構(gòu)hostent的指針,該結(jié)構(gòu)中包含了該主機(jī)的所有IPv4地址或IPv6地址。具體使用方法如下:#include <netdb.h>struct hostent *gethostbyname(const char *hostname);此函數(shù)返回的非空指針指向下面的hostent結(jié)構(gòu):struct hostent char *h_name; /*official name of host*/char *h_aliases; /*pointer to array of pointers to alias names*/int h_
11、addrtype;/*host address type: AF_INET or AF_INET6*/int h_length; /*length of address:4 or 16*/char *h_addr_list; /*ptr to array of ptrs with IPv4 or IPv6 addrs*/;#define h_addr h_addr_list0/*first address in list*/按照DNS,gethostbyname函數(shù)執(zhí)行一個對A記錄的查詢或?qū)AAA記錄的查詢,它返回IPv4地址或IPv6地址。圖5-2所示為結(jié)構(gòu)hostent和它所指向的各種信
12、息的關(guān)系,該圖中被查詢的主機(jī)有兩個別名和三個IPv4地址。在這些字段中,正式的主機(jī)名和所有的別名都是以空字符(“0”)結(jié)尾的C字符串。當(dāng)返回IPv6地址時,結(jié)構(gòu)hostent的成員h_addrtype被設(shè)置為AF_INET6,成員h_length被設(shè)置為16。從BIND 4.9.2版本開始,新的gethostbyname版本允許主機(jī)名參數(shù)是點(diǎn)分十進(jìn)制數(shù)串,即下面調(diào)用是可行的: hptr=gethostbyname(“”);gethostbyname函數(shù)與其它套接口函數(shù)的不同之處在于:當(dāng)發(fā)生錯誤時,它不設(shè)置errno,而是將全局整數(shù)h_errno設(shè)置為定義在頭文件<netdb.h>
13、中的下列常值中的一個:l HOST_NOT_FOUNDl TRY_AGAINl NO_RECOVERYl NO_DATA (等同于NO_ADDRESS)錯誤NO_DATA表示指定的名字有效,但它既沒有A記錄,也沒有AAAA記錄。只有MX記錄 的主機(jī)名就是這樣的例子。BIND的當(dāng)前版本提供函數(shù)hstrerror,它將h_errno的值作為唯一的參數(shù),返回一個指向相應(yīng)錯誤說明的const char *型指針。 正式主機(jī)名 0h_nameh_aliases別名10AF_INETh_addrtype4NULLh_length別名20h_addr_listIP地址1(in_addr)IP地址2(in_a
14、ddr)NULLIP地址3(in_addr)圖5-2 結(jié)構(gòu)hostent及其包含信息下面程序給出了一個調(diào)用gethostbyname函數(shù)的例子,它可有任意數(shù)目的命令行參數(shù),輸出所有返回的信息。#include"unp.h"intmain(int argc, char *argv)char*ptr, *pptr;charstrINET6_ADDRSTRLEN;struct hostent*hptr;while (-argc > 0) ptr = *+argv;if ( (hptr = gethostbyname(ptr) = NULL) err_msg("ge
15、thostbyname error for host: %s: %s",ptr, hstrerror(h_errno);continue;printf("official hostname: %sn", hptr->h_name);for (pptr = hptr->h_aliases; *pptr != NULL; pptr+)printf("talias: %sn", *pptr);switch (hptr->h_addrtype) case AF_INET:#ifdefAF_INET6case AF_INET6:#end
16、ifpptr = hptr->h_addr_list;for ( ; *pptr != NULL; pptr+)printf("taddress: %sn",Inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str);break;default:err_ret("unknown address type");break;exit(0);5.3 RES_USE_INET6解析器選項BIND的較新版本(4.9.4及其以后版本)提供了一個名為RES_USE_INET6的解析器選項,用戶可以用三種不同的方法
17、來設(shè)置它。用戶可以用此選項來通知解析器想讓gethostbyname返回IPv6地址而不是IPv4地址。具體方法如下:1 應(yīng)用程序本身可以設(shè)置此選項,首先調(diào)用解析器的res_init函數(shù),然后打開該選項:#include <resolv.h>res_init();_res.options |= RES_USE_INT6;上面語句必須在第一次調(diào)用gethostbyname或gethostbyname2之前完成。此選項僅對那些設(shè)置了此選項的應(yīng)用程序才有效。2 如果環(huán)境變量RES_OPTIONS含有串inet6,則此選項打開。此選項的作用依賴于環(huán)境變量的范圍。例如,如果用戶在.profi
18、le文件(使用Korn Shell)中以exports屬性設(shè)置它,例如:export RES_OPTIONS=inet6則它對從登錄shell開始運(yùn)行的每個程序都有效。但如果用戶僅在命令行上設(shè)置該環(huán)境變量,則它僅對那個命令有影響。3 解析器配置文件(一般為/etc/resolv.conf)可以包含如下行:options inet6在解析器配置文件中設(shè)置此選項影響主機(jī)上調(diào)用解析器函數(shù)的所有應(yīng)用程序,因此,這項技術(shù)要直到結(jié)構(gòu)hostent中返回的IPv6地址可以被主機(jī)上的所有應(yīng)用程序所處理時才能使用。第一種方法以每個應(yīng)用程序為基礎(chǔ)設(shè)置此選項,第二種方法以每個用戶為基礎(chǔ),第三種方法以整個系統(tǒng)為基礎(chǔ)。
19、當(dāng)IPv6支持增加到BIND 4.9.4時,函數(shù)gethostbyname2也增加進(jìn)去,它有兩個參數(shù)允許用戶指定地址族。具體使用方法如下:#include <netdb.h>struct hostent * gethostbyname2(const char *hostname, int family);該函數(shù)成功時返回非空指針,出錯時返回空指針并設(shè)置h_errno值。該函數(shù)的返回值與gethostbyname的返回值相同,為一個指向結(jié)構(gòu)hostent的指針,且此結(jié)構(gòu)也保持不變。該函數(shù)的邏輯依賴于參數(shù)family和解析器選項RES_USE_INET6。對于新選項RES_USE_IN
20、ET6,函數(shù)gethostbyname和gethostbyname2的操作:l RES_USE_INET6選項是否打開;l gethostbyname2的第二個參數(shù)是AF_INET還是AF_INET6;l 解析器是搜索A記錄還是搜索AAAA記錄;l 返回地址長度是4還是16。函數(shù)gethostbyname2的操作如下:l 如果參數(shù)family是AF_INET,則查詢A記錄。若不成功,則返回一個空指針,若成功,則返回地址的類型和大小依賴于新的解析器選項RES_USE_INET6:若選項未設(shè)置(缺省),則返回IPv4地址,結(jié)構(gòu)hostent的成員h_length的值將為4;若選項設(shè)置,則返回IPv
21、4映射的IPv6地址,結(jié)構(gòu)hostent的成員h_length的值將為16。l 如果參數(shù)family為AF_INET6,則查詢AAAA記錄。若成功,則返回IPv6地址,結(jié)構(gòu)hostent的成員h_length的值將為16;否則返回一個空指針。表5-1詳細(xì)地總結(jié)了對于新選項RES_USE_INET6,函數(shù)gethostbyname和gethostbyname2的操作。表5-1 解析器選項RES_USE_INET6與函數(shù)gethostbyname和gethostbyname2RES_USE_INET6選項關(guān)閉打開gethostbyname(host)搜索A記錄,若找到,返回IPv4地址(h_len
22、gth=4),否則返回錯誤。這為現(xiàn)存的IPv4應(yīng)用程序提供了向后兼容性搜索AAAA記錄,若找到,返回IPv6地址(h_length=16),否則搜索A記錄。若找到,返回IPv4映射的IPv6地址(h_length=16),否則返回錯誤gethostbyname2(host, AF_INET)搜索A記錄,若找到,返回IPv4地址(h_length=4),否則返回錯誤。搜索A記錄,若找到,返回IPv4映射的IPv6地址(h_length=16),否則返回錯誤gethostbyname2(host, AF_INET6)搜索AAAA記錄,若找到,返回IPv6地址(h_length=16),否則返回錯誤
23、搜索AAAA記錄,若找到,返回IPv6地址(h_length=16),否則返回錯誤如果應(yīng)用程序想強(qiáng)制某個指定地址類型的搜索:IPv4或IPv6,則可以使用gethostbyname2函數(shù)。但對應(yīng)用程序來說,調(diào)用gethostbyname函數(shù)似乎更常見,而且該函數(shù)的較新版本既可以返回IPv4地址,也可以返回IPv6地址。如果解析器沒有被初始化(沒有設(shè)置標(biāo)志RES_INIT),則調(diào)用res_init。此初始化函數(shù)檢查并處理環(huán)境變量RES_OPTIONS。如果這個變量包含串inet6或如果解析器配置文件包含行options inet6,則標(biāo)志RES_USE_INET6由res_init設(shè)置。res_
24、init一般由函數(shù)gethostbyname或gethostbyaddr在第一次被應(yīng)用程序調(diào)用時自動調(diào)用的。此外,應(yīng)用程序也可以調(diào)用res_init,然后顯式設(shè)置標(biāo)志RES_USE_INET6??傊?dāng)選項RES_USE_INET6打開且應(yīng)用程序調(diào)用gethostbyname時,應(yīng)用程序通知解析器:返回IPv6地址,首先搜索AAAA記錄,如果未找到則搜索A記錄,如果A記錄找到則返回IPv4映射的IPv6地址。5.4 與名字和地址有關(guān)的常用函數(shù)5.4.1 gethostbyaddr函數(shù)函數(shù)gethostbyaddr取一個二進(jìn)制的IP地址并試圖找到相應(yīng)的主機(jī)名,此函數(shù)與gethostbyname的
25、功能相反。gethostbyaddr返回一個指向結(jié)構(gòu)hostent的指針。具體使用方法如下:#include <netdb.h>struct hostent *gethostbyaddr(const char *addr, size_t len, int family);參數(shù)addr是一個真正指向含有IPv4或IPv6地址的結(jié)構(gòu)in_addr或in6_addr的指針;len是此結(jié)構(gòu)的大?。簩τ贗Pv4地址為4,對于IPv6地址為16;參數(shù)family或者是AF_INET或者是AF_INET6。按照DNS原理,gethostbyaddr在域in_中給IPv4地址在名
26、字服務(wù)員上查詢PTR記錄,或在域中給IPv6地址查詢PTR記錄。gethostbyaddr總有一個地址族參數(shù),所以當(dāng)加上IPv6支持到BIND時,無需另一個函數(shù)(類似于函數(shù)gethostbyname2)。但是,當(dāng)參數(shù)是IPv6地址時,仍有一些差別。下面的判斷按步驟進(jìn)行:1. 如果family是AF_INET6,len是16,且地址是IPv4映射的IPv6地址。則在域in_中查找地址的低32位(IP地址部分)。2. 如果family是AF_INET6,len是16,且地址是IPv4兼容的IPv6地址。則在域in_中查找地址的低32位(IP地址部分
27、)。3. 如果被查找的是IPv4地址(或參數(shù)family為AF_INET,或上述兩種情況中的一個為真)且解析器選項RES_USE_INET6設(shè)置,則返回的地址(參數(shù)addr的一個拷貝)被轉(zhuǎn)換為一個IPv4映射的IPv6地址:h_addrtype為AF_INET6,h_length為16。5.4.2 uname函數(shù)函數(shù)uname返回當(dāng)前主機(jī)的名字。它雖然不是解析器庫中的一部分,但它經(jīng)常與函數(shù)gethostbyname一起用來確定本地主機(jī)的IP地址。具體使用方法如下:#include <sys/utsname.h>int uname(struct ustname *name);該函數(shù)調(diào)
28、用成功時返回一個非負(fù)整數(shù),發(fā)生錯誤時返回-1。此函數(shù)裝填結(jié)構(gòu)utsname,其地址由調(diào)用者傳遞:#idefine UTS_NAMESIZE 16#define UTS_NODESIZE 256struct utsname char sysname _UTS_NAMESIZE; /*name of this operating systen*/char nodename_UTS_NODESIZE; /*name of this node*/char release_UTS_NAMESIZE; /*OS release level*/char version_UTS_NAMESIZE; /*OS
29、version level*/char machine_UTS_NAMESIZE; /*hardware type*/這里需要注意的是,Posix.1所規(guī)定的只是上面的五個結(jié)構(gòu)成員的名字以及每個數(shù)組是一個以空字符(“0”)終止的字符數(shù)組,對于每個數(shù)組的大小及內(nèi)容并未作任何說明。上面給出的大小來源于4.4BSD,其它操作系統(tǒng)采用不同的大小。從網(wǎng)絡(luò)程序設(shè)計角度來看,最嚴(yán)重的忽略是對數(shù)組nodename大小和內(nèi)容的定義。有些系統(tǒng)僅在此數(shù)組中存儲主機(jī)名(例如Jida),而另外一些系統(tǒng)存儲FQDN(例如J)。在有些操作系統(tǒng)如Solaris2.x上,既可以存放主機(jī)名,也可以存放FQDN,主要取決于管理員是
30、如何安裝操作系統(tǒng)的。為了確定本地主機(jī)的IP地址,用戶可以調(diào)用uname函數(shù)以得到主機(jī)名字,然后調(diào)用gethostbyname函數(shù)以得到它的所有IP地址。下面代碼說明了這些步驟。#include"unp.h"#include<sys/utsname.h>char *my_addrs(int *addrtype)struct hostent*hptr;struct utsnamemyname;if (uname(&myname) < 0)return(NULL);if ( (hptr = gethostbyname(myname.nodename) =
31、 NULL)return(NULL);*addrtype = hptr->h_addrtype;return(hptr->h_addr_list);上述函數(shù)返回值是結(jié)構(gòu)hostent的成員h_addr_list,即指向IP地址的指針數(shù)組。確定本地主機(jī)IP地址的另一種方法是ioctl的命令SIOCGIFCONF。5.4.3 gethostname函數(shù)函數(shù)gethostname的功能也是返回當(dāng)前主機(jī)的名字。具體使用方法如下:#include <unistd.h>int gethostname(char *name, size_t namelen);name是指向主機(jī)名存儲位
32、置的在指針,namelen是此數(shù)組的大小。如果有空間,主機(jī)名以空字符結(jié)束。主機(jī)名的最大值通常是由頭文件<sys/param.h>定義的常值MAXHOSTNAMELEN。從歷史上看,uname由系統(tǒng)V定義,而gethostbyname由Berkeley定義。Posix.1 指定uname,但Unix 98兩者都支持。5.4.4 getservbyname和getservbyport函數(shù)服務(wù)器也常常由名字來標(biāo)識。如果在代碼中,通過服務(wù)器的名字而不是通過服務(wù)器端口號來認(rèn)知它,而且如果從主機(jī)到端口號的映射包含在一個文件中(通常是/etc/services),則如果端口號改變,用戶所需要做的
33、修改就是改動/etc/services文件中的一行,而不需要重新編譯應(yīng)用程序。getservbyname函數(shù)可以根據(jù)給定的名字查找相應(yīng)的服務(wù),具體使用方法如下:#include <netdb.h>struct servent * getservbyname(const char *servname, const char *protoname);該函數(shù)調(diào)用出錯時返回空指針,成功時返回非空指針,返回一個指向下面所示結(jié)構(gòu)的指針:struct servent char * s_name; /*official service name*/char * s_aliases; /*alias
34、 list*/int s_port; /*port number, network-byte order*/char * s_proto; /*protocol to use*/;服務(wù)器名字servname必須指定,如果還指定了一個協(xié)議,則結(jié)果表項也必須有匹配的協(xié)議。有些因特網(wǎng)服務(wù)既可使用UDP協(xié)議,又可以使用TCP協(xié)議,例如NFS(網(wǎng)絡(luò)文件系統(tǒng));而其它一些服務(wù)則僅支持單個協(xié)議。如果protoname沒有指定且支持多個協(xié)議,則返回哪個端口是依賴于具體實現(xiàn)的。一般來說,支持多個協(xié)議的服務(wù)常常使用相同的TCP和UDP端口號。結(jié)構(gòu)servent中主要成員是端口號。由于端口號是以網(wǎng)絡(luò)字節(jié)順序返回的。
35、在將它存儲于套接口地址結(jié)構(gòu)時,絕對不能調(diào)用htons函數(shù)。對此函數(shù)的典型調(diào)用是:struct servent *sptr;sptr= getservbyname(“domain”, “udp”); /*DNS using UDP*/sptr= getservbyname(“ftp”, “tcp”); /*FTP using TCP*/sptr= getservbyname(“ftp”, NULL); /*FTP using TCP*/sptr= getservbyname(“ftp”, “udp”); /*this call will fail*/由于FTP僅支持TCP,所以第二個調(diào)用和第三個
36、調(diào)用的結(jié)果是相同的,第四個調(diào)用將失敗。下面是關(guān)于文件/etc/services中的內(nèi)容:ftp 21/tcp telnet 23/tcp tftp 69/udp login 513/tcp函數(shù)getservbyport在給定斷口號和可選協(xié)議后查找相應(yīng)的服務(wù)。具體使用方法如下:#include <netdb.h>struct servent * getservbyport(int port, const char *protoname);port值必須為網(wǎng)絡(luò)字節(jié)順序。對此函數(shù)的典型調(diào)用是:struct servent *sptr;sptr=getservbyport(htons(53
37、), “udp”); /*DNS using UDP*/sptr=getservbyport(htons(21), “tcp”); /*FTP using TCP*/sptr=getservbyport(htons(21), NULL); /*FTP using TCP*/sptr=getservbyport(htons(21), “udp”); /*this call will fail*/對于UDP,由于沒有服務(wù)使用端口21,所以最后一個調(diào)用將失敗。這里用戶需要清楚,有些端口對于TCP可能用于一種服務(wù),但對于UDP,同樣的端口號也完全可能用于不同的服務(wù)。下面代碼是使用gethostbyna
38、me和getservbyname函數(shù)實現(xiàn)TCP時間/日期顧客程序的例子。#include"unp.h"intmain(int argc, char *argv)intsockfd, n;charrecvlineMAXLINE + 1;struct sockaddr_inservaddr;struct in_addr*pptr;struct hostent*hp;struct servent*sp;if (argc != 3)err_quit("usage: daytimetcpcli1 <hostname> <service>")
39、;if ( (hp = gethostbyname(argv1) = NULL)err_quit("hostname error for %s: %s", argv1, hstrerror(h_errno);if ( (sp = getservbyname(argv2, "tcp") = NULL)err_quit("getservbyname error for %s", argv2);pptr = (struct in_addr *) hp->h_addr_list;for ( ; *pptr != NULL; pptr+)
40、 sockfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr);servaddr.sin_family = AF_INET;servaddr.sin_port = sp->s_port;memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr);printf("trying %sn", Sock_ntop(SA *) &servaddr, sizeof(servaddr);if (connect(sock
41、fd, (SA *) &servaddr, sizeof(servaddr) = 0)break;/* success */err_ret("connect error");close(sockfd);if (*pptr = NULL)err_quit("unable to connect");while ( (n = Read(sockfd, recvline, MAXLINE) > 0) recvlinen = 0;/* null terminate */Fputs(recvline, stdout);exit(0);5.4.5 其它網(wǎng)
42、絡(luò)相關(guān)信息本章的重點(diǎn)在于主機(jī)名與IP地址、服務(wù)名與端口號。其實應(yīng)用程序可能需要查詢和網(wǎng)絡(luò)相關(guān)的四種類型信息:主機(jī)、網(wǎng)絡(luò)、協(xié)議與服務(wù)。大多數(shù)查詢都是針對主機(jī)的(gethostbyname和gethostbyaddr),有一小部分是針對網(wǎng)絡(luò)服務(wù)的(getservbyname和getservbyport),針對網(wǎng)絡(luò)和協(xié)議的查詢就更少了。所有四類信息都可以存儲在文件中,而且每類信息都定義三個函數(shù):1. 函數(shù)getXXXent讀文件中的下一表項,在必要時可以打開文件。2. 函數(shù)setXXXent打開(如果文件沒有打開)并回繞文件。3. 函數(shù)endXXXent關(guān)閉文件。每類信息都定義了自己的結(jié)構(gòu),這些定義
43、包含在<netdb.h>中:hostent、netent、protoent和servent結(jié)構(gòu)。除了三個用于文件的順序處理的get、set和end函數(shù)外,每類信息還提供了一些鍵值查詢(keyed lookup)函數(shù)。它們順序瀏覽文件(調(diào)用函數(shù)getXXXent來讀每一行),但不返回每一行給調(diào)用者,而是查找一個與某參數(shù)匹配的表項。這些鍵值查詢函數(shù)的名字類似函數(shù)getXXXbyYYY。例如,針對主機(jī)信息的兩個關(guān)鍵字查詢函數(shù)是gethostbyname(查找與主機(jī)名匹配的表項)和gethostbyaddr(查找與IP地址匹配的表項)。表5-2對此作了總結(jié)。表5-2 四類與網(wǎng)絡(luò)相關(guān)的信息信
44、息數(shù)據(jù)文件結(jié)構(gòu)鍵值搜索函數(shù)主機(jī)/etc/hostshostentgethostbyaddr, gethostbyname網(wǎng)絡(luò)/etc/networksnetentgetnetbyaddr, getnetbyname協(xié)議/etc/protocolsprotoentgetprotobyname, getprotobynumber服務(wù)/etc/servicesserventgetservbyname, getservbyport當(dāng)DNS正在使用時,只有主機(jī)和網(wǎng)絡(luò)信息是通過DNS提供的,服務(wù)和協(xié)議信息一般要從相應(yīng)的文件中讀。還有一種名字和地址的轉(zhuǎn)換方法是直接調(diào)用解析器函數(shù),而不使用gethostbyn
45、ame和gethostbyaddr。用這種方法來調(diào)用DNS的一個程序是sendmail,它搜索MX記錄,這是gethostbyXXX函數(shù)無法做到的。解析器函數(shù)都有以res_開頭的名字。5.5 套接字選項網(wǎng)絡(luò)系統(tǒng)是通過核心的套接字結(jié)構(gòu)來實現(xiàn)對傳輸層的抽象,系統(tǒng)為用戶提供了獲取和修改套接字結(jié)構(gòu)中一些屬性的函數(shù),通過修改這些屬性,用戶可以調(diào)整套接字的性能,進(jìn)而調(diào)整用戶編寫的網(wǎng)絡(luò)應(yīng)用的性能。有很多方法可以用來獲取和設(shè)置套接口的選項,主要有:l 函數(shù)getsockopt和setsockoptl 函數(shù)fcntll 函數(shù)ioctl5.5.1 獲取和設(shè)置套接口選項系統(tǒng)提供了函數(shù)getsockopt和setso
46、ckopt,分別用于獲取套接口選項和設(shè)置套接口選項,這兩個函數(shù)僅用于套接口。具體使用方法如下:#include <sys/socket.h>int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t *optlen); sockfd是一個已經(jīng)打開的套接口描述符,level是選項的層次,它指定系統(tǒng)中解釋選項的代碼:普通
47、套接口代碼或者特定于協(xié)議的代碼,即通用套接口(SOL_SOCKET)、IP層套接口(IPPROTO_IP)和TCP套接口選項(IPPROTO_TCP)等層次。通用套接口選項一般可適用于TCP/UDP套接口,而TCP套接口選項只適用于TCP套接口。optname是選項的名字。optval是一個指向變量的指針,用于存放獲取或者設(shè)置的選項值的空間,此變量的大小由最后一個參數(shù)指定。由于不同的選項的數(shù)據(jù)類型不同,因此使用的是void *類型的指針。表5-3總結(jié)了可由getsockopt獲取或者由setsockopt設(shè)置的一些選項。表中數(shù)據(jù)類型列給出了指針optval必須指向的每個選項的數(shù)據(jù)類型表5-3
48、套接口選項級別選項名獲取設(shè)置說明標(biāo)志數(shù)據(jù)類型SOL_SOCKETSO_BROADCAST*允許發(fā)送廣播數(shù)據(jù)報*intSO_DEBUG*使能調(diào)試跟蹤*intSO_DONTROUTE*不使用路由表尋找路由*intSO_ERROR*獲取待處理錯誤并清除intSO_KEEPALIVE*周期地測試連接是否存活*intSO_LINGER*若有數(shù)據(jù)待發(fā)送則延遲關(guān)閉struct lingerSO_OOBINLINE*讓接收到的帶外數(shù)據(jù)繼續(xù)在線存放*intSO_RCVBUF*接收緩沖區(qū)大小intSO_SNDBUF*發(fā)送緩沖區(qū)大小intSO_RCVLOWAT* 接收緩沖區(qū)的下限指示intSO_SNDLOWAT*發(fā)
49、送緩沖區(qū)的下限指示intSO_RCVTIMEO*接收超時struct timevalSO_SNDTIMEO*發(fā)送超時struct timevalSO_REUSEADDR*允許本地地址重用*intSO_REUSEPORT* 允許端口重用*intSO_TYPE*獲取套接口的類型intSO_USELOOPBACK*路由套接口取得所發(fā)送數(shù)據(jù)的拷貝*intIPPROTO_IPIP_HDRINCL*IP頭部包括數(shù)據(jù)*intIP_OPTIONS*IP 頭部選項 struct ipoptionIP_RECVDSTADDR*返回目的IP地址*intIP_RECVIF*返回接收到的接口索引*intIP_TOS*服
50、務(wù)類型和優(yōu)先權(quán)intIP_TTL*存活時間intIP_MULTICAST_IF*指定外出接口struct in_addrIP_MULTICAST_TTL*指定外出TTLu_charIP_MULTICAST_LOOP*指定是否回饋u_charIP_ADD_MEMBERSHIP*加入多播組struct ip_mreqIP_DROP_MEMBERSHIP*離開多播組struct ip_mreqIPPROTO_ICMPV6ICMP6_FILTER*指定傳遞的ICMPV6消息類型struct icmp6_filterIPPROTO_IPV6IPV6_ADDRFORM*改變套接口的地址結(jié)構(gòu)intIPV6_
51、CHECKSUM*原始套接口的校驗和字段偏移intIPV6_DSTOPTS*接收目標(biāo)選項*intIPV6_HOPLIMIT*接受單播跳限*intIPV6_HOPOPTS* 接受跳步選項*intIPV6_NEXTHOP*指定下一跳地址*struct sockaddrIPV6_PKTINFO*接收分組信息*intIPV6_PKTOPTIONS*指定分組選項intIPV6_RTHDR*接收源路由*intIPV6_UNICAST_HOPS*缺省單播跳限intIPV6_MULTICAST_IF*指定外出接口struct in6_addrIPV6_MULTICAST_HOPS*指定外出跳限u_intIPV
52、6_MULTICAST_LOOP*指定是否回饋*u_intIPV6_ADD_MEMBERSHIP*加入多播組struct ipv6_mreqIPV6_DROP_MEMBERSHIP*離開多播組struct ipv6_mreqIPPROTO_TCPTCP_KEEPALIVE*控測對方是否存活前連接閑置秒數(shù)intTCP_MAXRT*TCP最大重傳時間intTCP_MAXSEG*TCP最大分節(jié)大小intTCP_NONDELAY*禁止Nagle算法*intTCP_STDURG*緊急指針的解釋*int有兩種基本類型的套接口選項:打開或者關(guān)閉某個特性的二進(jìn)制選項(標(biāo)志),取得或者返回用戶可以設(shè)置或檢查的特
53、定值的選項。標(biāo)有“標(biāo)志”的列指明選項是否為標(biāo)志選項。當(dāng)給這些標(biāo)志選項調(diào)用函數(shù)getsockopt時,optval是一個整數(shù)。optval中返回的值是0表示選項關(guān)閉,非0表示選項打開。類似地,函數(shù)setsockopt要求一個非0的optval來打開選項,要求用0來關(guān)閉選項。如果“標(biāo)志”不含有“*”,則選項用來在用戶進(jìn)程與系統(tǒng)間傳遞指定數(shù)據(jù)類型的值。5.5.2 通用套接口選項基本套接口選項是協(xié)議無關(guān)的,即它們由內(nèi)核中的協(xié)議無關(guān)代碼處理,而不是由諸如IPv6這樣的一類特殊的協(xié)議模塊來處理。但是這些選項僅能應(yīng)用到某些確定類型的套接口中。例如,盡管SO_BROADCAST套接口選項是一個基本選項,但它僅能應(yīng)用于數(shù)據(jù)報套接口。SO_BROADCAST此選項使能或者禁止套接口發(fā)送廣播消息。在網(wǎng)絡(luò)通信中,如果一個進(jìn)程需要發(fā)送廣播消息,必須滿足兩個條件:硬件必須支持廣播,例如以太網(wǎng);必須使用UDP數(shù)據(jù)報來發(fā)送廣播消息,TCP套接口不能發(fā)送廣播消息。由于一個應(yīng)用程序發(fā)送一個廣播數(shù)據(jù)報之前必須設(shè)置此套接口,因此它能有效防止該進(jìn)程在應(yīng)用程序未設(shè)計成能廣播時就發(fā)送廣播消息。套接口的缺省是禁止廣播信息的發(fā)送。如果UDP程序希望發(fā)送廣播消息,則可以使用下面語句修改設(shè)置。int b_broadcast_on=1;setsoc
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 農(nóng)業(yè)金融資本投入與運(yùn)營合作合同書
- 現(xiàn)代教育技術(shù)應(yīng)用與創(chuàng)新實踐題庫
- 保險行業(yè)數(shù)字化理賠服務(wù)智能審核系統(tǒng)構(gòu)建報告
- 綠色建筑標(biāo)準(zhǔn)與評價體系2025年研究報告
- 2025年新能源微電網(wǎng)穩(wěn)定性控制與可再生能源并網(wǎng)技術(shù)研究報告
- 校園安全管理創(chuàng)新2025:基于物聯(lián)網(wǎng)技術(shù)的智慧校園安全監(jiān)測報告
- 基于邊緣計算的2025年城市軌道交通智慧運(yùn)維系統(tǒng)實時監(jiān)控與數(shù)據(jù)分析報告
- 2025年在線教育平臺教學(xué)質(zhì)量評估體系創(chuàng)新與實踐報告
- 醫(yī)療器械臨床試驗質(zhì)量管理規(guī)范化對產(chǎn)品上市的影響報告
- 河北省衡水市河北武強(qiáng)中學(xué)2024-2025學(xué)年高二下學(xué)期期末考試歷史試題(含答案)
- 北京市2025學(xué)年高二(上)第一次普通高中學(xué)業(yè)水平合格性考試物理試題(解析版)
- 2025年四川省高考物理試卷真題(含答案)
- 炸雞店的產(chǎn)品創(chuàng)新與口味調(diào)研
- 數(shù)據(jù)庫應(yīng)用技術(shù)-第三次形考作業(yè)(第10章~第11章)-國開-參考資料
- 中建epc人防工程施工方案
- 湖南省長沙市雨花區(qū)2023-2024學(xué)年三年級下學(xué)期期末考試英語試題
- MOOC 新媒體文化十二講-暨南大學(xué) 中國大學(xué)慕課答案
- 危險貨物道路運(yùn)輸安全生產(chǎn)管理制度
- GB∕T 8110-2020 熔化極氣體保護(hù)電弧焊用非合金鋼及細(xì)晶粒鋼實心焊絲
- 【完美排版】山東科技出版社二年級下冊綜合實踐活動教案
- 公共政策學(xué)(第三版)-課件
評論
0/150
提交評論