




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第五章 名字與地址轉(zhuǎn)換5.1 域名系統(tǒng)盡管通過(guò)IP地址可以唯一地識(shí)別主機(jī)上的網(wǎng)絡(luò)接口,從而訪問(wèn)網(wǎng)絡(luò)中的每個(gè)主機(jī)。但是,由于IP地址不便于人們記憶,因此人們還是習(xí)慣于使用主機(jī)名來(lái)訪問(wèn)網(wǎng)絡(luò)。隨著IPv6協(xié)議的不斷廣泛應(yīng)用,數(shù)值地址變得更長(zhǎng),手工鍵入一個(gè)地址更容易出錯(cuò)。在大多數(shù)操作系統(tǒng)中,任何應(yīng)用程序都可以調(diào)用一個(gè)標(biāo)準(zhǔn)的庫(kù)函數(shù)來(lái)查看給定名字的主機(jī)的IP地址(UNIX系統(tǒng)中函數(shù)名);同樣,系統(tǒng)還提供了一個(gè)逆函數(shù),即給定主機(jī)的IP地址,查看它所對(duì)應(yīng)的主機(jī)名。大多數(shù)使用主機(jī)名作為參數(shù)的應(yīng)用程序也支持把IP地址作為參數(shù)。域名系統(tǒng)DNS(Domain Name System)主要用于主機(jī)名與IP地址間的映射。
2、主機(jī)名可以是簡(jiǎn)單名字,例如Jida,也可以是全限定域名FQDN(Fully Qualified Domain Name),例如。嚴(yán)格地說(shuō),F(xiàn)QDN也稱為絕對(duì)名字(absolute name),因此必須以一個(gè)點(diǎn)號(hào)結(jié)尾,但用戶經(jīng)常省略最后的點(diǎn)號(hào)。在Internet上使用了基于層次型的名字管理機(jī)制。在Internet的層次型名字管理中,先由中央管理機(jī)構(gòu)(例如Internet的NIC)將最高一級(jí)的名字空間進(jìn)行劃分,并將相應(yīng)部分的管理權(quán)交給相應(yīng)的機(jī)構(gòu),各管理機(jī)構(gòu)可對(duì)名字空間進(jìn)行進(jìn)一步的劃分。一般來(lái)說(shuō),最高一級(jí)的名字空間的劃分是基于“網(wǎng)絡(luò)節(jié)點(diǎn)名”(site name)的。網(wǎng)絡(luò)節(jié)點(diǎn)的概念是對(duì)Internet
3、整個(gè)網(wǎng)絡(luò)的一部分(通常由若干個(gè)網(wǎng)絡(luò)構(gòu)成)的一種抽象,這些網(wǎng)絡(luò)的組織關(guān)系或地理位置聯(lián)系非常緊密,可以將它們看成一個(gè)節(jié)點(diǎn)。各個(gè)網(wǎng)絡(luò)節(jié)點(diǎn)中又可劃分成不同的管理組。組名下面是主機(jī)的本地名。典型的Internet層次型主機(jī)名由三部分構(gòu)成:本地名稱.管理組名.網(wǎng)絡(luò)節(jié)點(diǎn)名例如,其中cn屬于第一級(jí)的名字空間,代表國(guó)家;第二級(jí)域?yàn)?,代表教育機(jī)構(gòu),最低一級(jí)代表吉林大學(xué)。5.1.1 資源記錄在TCP/IP環(huán)境中,域名系統(tǒng)(DNS)是一個(gè)分布式數(shù)據(jù)庫(kù)系統(tǒng),通過(guò)它來(lái)提供IP地址和主機(jī)名之間的映射。DNS中的條目稱為資源記錄RR(resource record),僅有少數(shù)幾類(lèi)RR會(huì)影響名字與地址轉(zhuǎn)換。AA記錄將主機(jī)名映射
4、為32位的IPv4地址。例如,這里有域中關(guān)于主機(jī)solaris的四個(gè)DNS記錄,其中第一個(gè)就是一個(gè)A記錄:IN AAAA5f1b:df00:ce3e:e200:0020:0800:2078:e3e3IN MX5 .IN MX10 .AAAAAAAA記錄將主機(jī)名映射為128位的IPv6地址。PTRPTR記錄(稱為“指針記錄”)將IP地址映射為主機(jī)名。對(duì)于IPv4地址,32位地址的四個(gè)字節(jié)順序反轉(zhuǎn),每個(gè)字節(jié)都轉(zhuǎn)換成它的十進(jìn)制ASCII值(0到255),然后附上,結(jié)果串用于PTR查詢。對(duì)于IPv6地址,128位地址中的32個(gè)4位組順序反轉(zhuǎn),每組被轉(zhuǎn)換成相應(yīng)的十六進(jìn)制ASCII
5、值(0到9,a到f),并附上.例如,主機(jī)solaris的兩個(gè)PTR記錄為:06.和3.。MXMX記錄指定一個(gè)主機(jī)作為某主機(jī)的“郵件交換器”。在上面主機(jī)的solaris例子中,提供了兩個(gè)MX記錄,第一個(gè)記錄的優(yōu)先級(jí)是5,第二個(gè)記錄的優(yōu)先級(jí)是10,當(dāng)有多個(gè)MX記錄存在時(shí),需按優(yōu)先級(jí)值的順序使用,從最小值開(kāi)始。CNAMECNAME代表“canonical name(規(guī)范名字)”,其常見(jiàn)的用法是為常用服務(wù)如
6、WWW和FTP指派一個(gè)CNAME記錄。如果用戶使用這些服務(wù)名而不是實(shí)際上的主機(jī)名,則它在服務(wù)挪到其它主機(jī)上時(shí)是透明的。例如,主機(jī)Jida的CNAME如下:5.1.2 解析器和名字服務(wù)器組織運(yùn)行一個(gè)或多個(gè)名字服務(wù)器(name server),它們通常就是所說(shuō)的BIND(Berkeley Internet Name Domain)程序。任何應(yīng)用程序,通過(guò)調(diào)用稱為解析器(resolver)的庫(kù)中的函數(shù)來(lái)與DNS服務(wù)器聯(lián)系。應(yīng)用程序用來(lái)將主機(jī)名轉(zhuǎn)換為IP地址或進(jìn)行相反過(guò)程的一組函數(shù)稱為解析器。最常見(jiàn)的解析器函數(shù)是gethostbyname和gethostbyaddr,前者將主機(jī)名映射為IP地址,后者執(zhí)
7、行相反的映射。圖5-1說(shuō)明了應(yīng)用進(jìn)程、解析器和名字服務(wù)器的典型關(guān)系。解析器代碼包含在系統(tǒng)庫(kù)中,在構(gòu)造應(yīng)用程序時(shí)被鏈接到應(yīng)用程序中。應(yīng)用程序代碼使用正常的函數(shù)調(diào)用來(lái)調(diào)用解析器代碼,最典型的就是調(diào)用函數(shù)gethostbyname和gethostbyaddr。應(yīng)用進(jìn)程應(yīng)用程序代碼函數(shù)返回函數(shù)調(diào)用UDP請(qǐng)求遠(yuǎn)程名字服務(wù)器本地名字服務(wù)器解析器代碼UDP應(yīng)答解析器配置文件圖5-1 應(yīng)用進(jìn)程、解析器和名字服務(wù)器的關(guān)系解析器代碼讀其依賴于系統(tǒng)的配置文件來(lái)確定組織的名字服務(wù)器們的所在位置。文件/etc/resolv.conf一般包含本地名字服務(wù)器的IP地址。解析器使用UDP給本地名字服務(wù)器發(fā)查詢,如果本地名字服
8、務(wù)器不知道答案,它也可以使用UDP在整個(gè)因特網(wǎng)上給其它名字服務(wù)器發(fā)查詢。5.1.3 DNS替代方法不使用DNS也可以得到主機(jī)的名字和地址信息,最常用的替代方法為靜態(tài)主機(jī)文件(一般為文件/etc/hosts)或網(wǎng)絡(luò)信息系統(tǒng)NIS(Network Information System)。這里需要注意的是,管理員如何配置一個(gè)主機(jī)來(lái)使用不同的名字服務(wù)是依賴于不同的實(shí)現(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。如果一個(gè)名字服務(wù)器將為主機(jī)名查找所用,則所有這些系統(tǒng)都使用文件/etc/resolv.conf來(lái)指定此名字服務(wù)器的IP地址。這些差異一般對(duì)應(yīng)用程序開(kāi)發(fā)人員透明,因此,用戶只需調(diào)用gethostbyname和gethostbyaddr這樣的解析器函數(shù)就可以了。5.2 gethostbyname函數(shù)計(jì)算機(jī)主機(jī)通常以人們可讀的名字被認(rèn)知,尤其是從IPv4協(xié)議向IPv6協(xié)議移植時(shí),由于IPv6地址比IPv4地址要長(zhǎng)得多,使用名字服務(wù)顯得更加正確和重要。查找主機(jī)名最基本的函數(shù)是ge
10、thostbyname,如果調(diào)用成功,它返回一個(gè)指向結(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í)行一個(gè)對(duì)A記錄的查詢或?qū)AAA記錄的查詢,它返回IPv4地址或IPv6地址。圖5-2所示為結(jié)構(gòu)hostent和它所指向的各種信
12、息的關(guān)系,該圖中被查詢的主機(jī)有兩個(gè)別名和三個(gè)IPv4地址。在這些字段中,正式的主機(jī)名和所有的別名都是以空字符(“0”)結(jié)尾的C字符串。當(dāng)返回IPv6地址時(shí),結(jié)構(gòu)hostent的成員h_addrtype被設(shè)置為AF_INET6,成員h_length被設(shè)置為16。從BIND 4.9.2版本開(kāi)始,新的gethostbyname版本允許主機(jī)名參數(shù)是點(diǎn)分十進(jìn)制數(shù)串,即下面調(diào)用是可行的: hptr=gethostbyname(“”);gethostbyname函數(shù)與其它套接口函數(shù)的不同之處在于:當(dāng)發(fā)生錯(cuò)誤時(shí),它不設(shè)置errno,而是將全局整數(shù)h_errno設(shè)置為定義在頭文件<netdb.h>
13、中的下列常值中的一個(gè):l HOST_NOT_FOUNDl TRY_AGAINl NO_RECOVERYl NO_DATA (等同于NO_ADDRESS)錯(cuò)誤NO_DATA表示指定的名字有效,但它既沒(méi)有A記錄,也沒(méi)有AAAA記錄。只有MX記錄 的主機(jī)名就是這樣的例子。BIND的當(dāng)前版本提供函數(shù)hstrerror,它將h_errno的值作為唯一的參數(shù),返回一個(gè)指向相應(yīng)錯(cuò)誤說(shuō)明的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及其包含信息下面程序給出了一個(gè)調(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解析器選項(xiàng)BIND的較新版本(4.9.4及其以后版本)提供了一個(gè)名為RES_USE_INET6的解析器選項(xiàng),用戶可以用三種不同的方法
17、來(lái)設(shè)置它。用戶可以用此選項(xiàng)來(lái)通知解析器想讓gethostbyname返回IPv6地址而不是IPv4地址。具體方法如下:1 應(yīng)用程序本身可以設(shè)置此選項(xiàng),首先調(diào)用解析器的res_init函數(shù),然后打開(kāi)該選項(xiàng):#include <resolv.h>res_init();_res.options |= RES_USE_INT6;上面語(yǔ)句必須在第一次調(diào)用gethostbyname或gethostbyname2之前完成。此選項(xiàng)僅對(duì)那些設(shè)置了此選項(xiàng)的應(yīng)用程序才有效。2 如果環(huán)境變量RES_OPTIONS含有串inet6,則此選項(xiàng)打開(kāi)。此選項(xiàng)的作用依賴于環(huán)境變量的范圍。例如,如果用戶在.profi
18、le文件(使用Korn Shell)中以exports屬性設(shè)置它,例如:export RES_OPTIONS=inet6則它對(duì)從登錄shell開(kāi)始運(yùn)行的每個(gè)程序都有效。但如果用戶僅在命令行上設(shè)置該環(huán)境變量,則它僅對(duì)那個(gè)命令有影響。3 解析器配置文件(一般為/etc/resolv.conf)可以包含如下行:options inet6在解析器配置文件中設(shè)置此選項(xiàng)影響主機(jī)上調(diào)用解析器函數(shù)的所有應(yīng)用程序,因此,這項(xiàng)技術(shù)要直到結(jié)構(gòu)hostent中返回的IPv6地址可以被主機(jī)上的所有應(yīng)用程序所處理時(shí)才能使用。第一種方法以每個(gè)應(yīng)用程序?yàn)榛A(chǔ)設(shè)置此選項(xiàng),第二種方法以每個(gè)用戶為基礎(chǔ),第三種方法以整個(gè)系統(tǒng)為基礎(chǔ)。
19、當(dāng)IPv6支持增加到BIND 4.9.4時(shí),函數(shù)gethostbyname2也增加進(jìn)去,它有兩個(gè)參數(shù)允許用戶指定地址族。具體使用方法如下:#include <netdb.h>struct hostent * gethostbyname2(const char *hostname, int family);該函數(shù)成功時(shí)返回非空指針,出錯(cuò)時(shí)返回空指針并設(shè)置h_errno值。該函數(shù)的返回值與gethostbyname的返回值相同,為一個(gè)指向結(jié)構(gòu)hostent的指針,且此結(jié)構(gòu)也保持不變。該函數(shù)的邏輯依賴于參數(shù)family和解析器選項(xiàng)RES_USE_INET6。對(duì)于新選項(xiàng)RES_USE_IN
20、ET6,函數(shù)gethostbyname和gethostbyname2的操作:l RES_USE_INET6選項(xiàng)是否打開(kāi);l gethostbyname2的第二個(gè)參數(shù)是AF_INET還是AF_INET6;l 解析器是搜索A記錄還是搜索AAAA記錄;l 返回地址長(zhǎng)度是4還是16。函數(shù)gethostbyname2的操作如下:l 如果參數(shù)family是AF_INET,則查詢A記錄。若不成功,則返回一個(gè)空指針,若成功,則返回地址的類(lèi)型和大小依賴于新的解析器選項(xiàng)RES_USE_INET6:若選項(xiàng)未設(shè)置(缺?。?,則返回IPv4地址,結(jié)構(gòu)hostent的成員h_length的值將為4;若選項(xiàng)設(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;否則返回一個(gè)空指針。表5-1詳細(xì)地總結(jié)了對(duì)于新選項(xiàng)RES_USE_INET6,函數(shù)gethostbyname和gethostbyname2的操作。表5-1 解析器選項(xiàng)RES_USE_INET6與函數(shù)gethostbyname和gethostbyname2RES_USE_INET6選項(xiàng)關(guān)閉打開(kāi)gethostbyname(host)搜索A記錄,若找到,返回IPv4地址(h_len
22、gth=4),否則返回錯(cuò)誤。這為現(xiàn)存的IPv4應(yīng)用程序提供了向后兼容性搜索AAAA記錄,若找到,返回IPv6地址(h_length=16),否則搜索A記錄。若找到,返回IPv4映射的IPv6地址(h_length=16),否則返回錯(cuò)誤gethostbyname2(host, AF_INET)搜索A記錄,若找到,返回IPv4地址(h_length=4),否則返回錯(cuò)誤。搜索A記錄,若找到,返回IPv4映射的IPv6地址(h_length=16),否則返回錯(cuò)誤gethostbyname2(host, AF_INET6)搜索AAAA記錄,若找到,返回IPv6地址(h_length=16),否則返回錯(cuò)誤
23、搜索AAAA記錄,若找到,返回IPv6地址(h_length=16),否則返回錯(cuò)誤如果應(yīng)用程序想強(qiáng)制某個(gè)指定地址類(lèi)型的搜索:IPv4或IPv6,則可以使用gethostbyname2函數(shù)。但對(duì)應(yīng)用程序來(lái)說(shuō),調(diào)用gethostbyname函數(shù)似乎更常見(jiàn),而且該函數(shù)的較新版本既可以返回IPv4地址,也可以返回IPv6地址。如果解析器沒(méi)有被初始化(沒(méi)有設(shè)置標(biāo)志RES_INIT),則調(diào)用res_init。此初始化函數(shù)檢查并處理環(huán)境變量RES_OPTIONS。如果這個(gè)變量包含串inet6或如果解析器配置文件包含行options inet6,則標(biāo)志RES_USE_INET6由res_init設(shè)置。res_
24、init一般由函數(shù)gethostbyname或gethostbyaddr在第一次被應(yīng)用程序調(diào)用時(shí)自動(dòng)調(diào)用的。此外,應(yīng)用程序也可以調(diào)用res_init,然后顯式設(shè)置標(biāo)志RES_USE_INET6。總之,當(dāng)選項(xiàng)RES_USE_INET6打開(kāi)且應(yīng)用程序調(diào)用gethostbyname時(shí),應(yīng)用程序通知解析器:返回IPv6地址,首先搜索AAAA記錄,如果未找到則搜索A記錄,如果A記錄找到則返回IPv4映射的IPv6地址。5.4 與名字和地址有關(guān)的常用函數(shù)5.4.1 gethostbyaddr函數(shù)函數(shù)gethostbyaddr取一個(gè)二進(jìn)制的IP地址并試圖找到相應(yīng)的主機(jī)名,此函數(shù)與gethostbyname的
25、功能相反。gethostbyaddr返回一個(gè)指向結(jié)構(gòu)hostent的指針。具體使用方法如下:#include <netdb.h>struct hostent *gethostbyaddr(const char *addr, size_t len, int family);參數(shù)addr是一個(gè)真正指向含有IPv4或IPv6地址的結(jié)構(gòu)in_addr或in6_addr的指針;len是此結(jié)構(gòu)的大小:對(duì)于IPv4地址為4,對(duì)于IPv6地址為16;參數(shù)family或者是AF_INET或者是AF_INET6。按照DNS原理,gethostbyaddr在域in_中給IPv4地址在名
26、字服務(wù)員上查詢PTR記錄,或在域中給IPv6地址查詢PTR記錄。gethostbyaddr總有一個(gè)地址族參數(shù),所以當(dāng)加上IPv6支持到BIND時(shí),無(wú)需另一個(gè)函數(shù)(類(lèi)似于函數(shù)gethostbyname2)。但是,當(dāng)參數(shù)是IPv6地址時(shí),仍有一些差別。下面的判斷按步驟進(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,或上述兩種情況中的一個(gè)為真)且解析器選項(xiàng)RES_USE_INET6設(shè)置,則返回的地址(參數(shù)addr的一個(gè)拷貝)被轉(zhuǎn)換為一個(gè)IPv4映射的IPv6地址:h_addrtype為AF_INET6,h_length為16。5.4.2 uname函數(shù)函數(shù)uname返回當(dāng)前主機(jī)的名字。它雖然不是解析器庫(kù)中的一部分,但它經(jīng)常與函數(shù)gethostbyname一起用來(lái)確定本地主機(jī)的IP地址。具體使用方法如下:#include <sys/utsname.h>int uname(struct ustname *name);該函數(shù)調(diào)
28、用成功時(shí)返回一個(gè)非負(fù)整數(shù),發(fā)生錯(cuò)誤時(shí)返回-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ī)定的只是上面的五個(gè)結(jié)構(gòu)成員的名字以及每個(gè)數(shù)組是一個(gè)以空字符(“0”)終止的字符數(shù)組,對(duì)于每個(gè)數(shù)組的大小及內(nèi)容并未作任何說(shuō)明。上面給出的大小來(lái)源于4.4BSD,其它操作系統(tǒng)采用不同的大小。從網(wǎng)絡(luò)程序設(shè)計(jì)角度來(lái)看,最嚴(yán)重的忽略是對(duì)數(shù)組nodename大小和內(nèi)容的定義。有些系統(tǒng)僅在此數(shù)組中存儲(chǔ)主機(jī)名(例如Jida),而另外一些系統(tǒng)存儲(chǔ)FQDN(例如J)。在有些操作系統(tǒng)如Solaris2.x上,既可以存放主機(jī)名,也可以存放FQDN,主要取決于管理員是
30、如何安裝操作系統(tǒng)的。為了確定本地主機(jī)的IP地址,用戶可以調(diào)用uname函數(shù)以得到主機(jī)名字,然后調(diào)用gethostbyname函數(shù)以得到它的所有IP地址。下面代碼說(shuō)明了這些步驟。#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ī)名存儲(chǔ)位
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ù)器也常常由名字來(lái)標(biāo)識(shí)。如果在代碼中,通過(guò)服務(wù)器的名字而不是通過(guò)服務(wù)器端口號(hào)來(lái)認(rèn)知它,而且如果從主機(jī)到端口號(hào)的映射包含在一個(gè)文件中(通常是/etc/services),則如果端口號(hào)改變,用戶所需要做的
33、修改就是改動(dòng)/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)用出錯(cuò)時(shí)返回空指針,成功時(shí)返回非空指針,返回一個(gè)指向下面所示結(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必須指定,如果還指定了一個(gè)協(xié)議,則結(jié)果表項(xiàng)也必須有匹配的協(xié)議。有些因特網(wǎng)服務(wù)既可使用UDP協(xié)議,又可以使用TCP協(xié)議,例如NFS(網(wǎng)絡(luò)文件系統(tǒng));而其它一些服務(wù)則僅支持單個(gè)協(xié)議。如果protoname沒(méi)有指定且支持多個(gè)協(xié)議,則返回哪個(gè)端口是依賴于具體實(shí)現(xiàn)的。一般來(lái)說(shuō),支持多個(gè)協(xié)議的服務(wù)常常使用相同的TCP和UDP端口號(hào)。結(jié)構(gòu)servent中主要成員是端口號(hào)。由于端口號(hào)是以網(wǎng)絡(luò)字節(jié)順序返回的。
35、在將它存儲(chǔ)于套接口地址結(jié)構(gòu)時(shí),絕對(duì)不能調(diào)用htons函數(shù)。對(duì)此函數(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,所以第二個(gè)調(diào)用和第三個(gè)
36、調(diào)用的結(jié)果是相同的,第四個(gè)調(diào)用將失敗。下面是關(guān)于文件/etc/services中的內(nèi)容:ftp 21/tcp telnet 23/tcp tftp 69/udp login 513/tcp函數(shù)getservbyport在給定斷口號(hào)和可選協(xié)議后查找相應(yīng)的服務(wù)。具體使用方法如下:#include <netdb.h>struct servent * getservbyport(int port, const char *protoname);port值必須為網(wǎng)絡(luò)字節(jié)順序。對(duì)此函數(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*/對(duì)于UDP,由于沒(méi)有服務(wù)使用端口21,所以最后一個(gè)調(diào)用將失敗。這里用戶需要清楚,有些端口對(duì)于TCP可能用于一種服務(wù),但對(duì)于UDP,同樣的端口號(hào)也完全可能用于不同的服務(wù)。下面代碼是使用gethostbyna
38、me和getservbyname函數(shù)實(shí)現(xiàn)TCP時(shí)間/日期顧客程序的例子。#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ù)名與端口號(hào)。其實(shí)應(yīng)用程序可能需要查詢和網(wǎng)絡(luò)相關(guān)的四種類(lèi)型信息:主機(jī)、網(wǎng)絡(luò)、協(xié)議與服務(wù)。大多數(shù)查詢都是針對(duì)主機(jī)的(gethostbyname和gethostbyaddr),有一小部分是針對(duì)網(wǎng)絡(luò)服務(wù)的(getservbyname和getservbyport),針對(duì)網(wǎng)絡(luò)和協(xié)議的查詢就更少了。所有四類(lèi)信息都可以存儲(chǔ)在文件中,而且每類(lèi)信息都定義三個(gè)函數(shù):1. 函數(shù)getXXXent讀文件中的下一表項(xiàng),在必要時(shí)可以打開(kāi)文件。2. 函數(shù)setXXXent打開(kāi)(如果文件沒(méi)有打開(kāi))并回繞文件。3. 函數(shù)endXXXent關(guān)閉文件。每類(lèi)信息都定義了自己的結(jié)構(gòu),這些定義
43、包含在<netdb.h>中:hostent、netent、protoent和servent結(jié)構(gòu)。除了三個(gè)用于文件的順序處理的get、set和end函數(shù)外,每類(lèi)信息還提供了一些鍵值查詢(keyed lookup)函數(shù)。它們順序?yàn)g覽文件(調(diào)用函數(shù)getXXXent來(lái)讀每一行),但不返回每一行給調(diào)用者,而是查找一個(gè)與某參數(shù)匹配的表項(xiàng)。這些鍵值查詢函數(shù)的名字類(lèi)似函數(shù)getXXXbyYYY。例如,針對(duì)主機(jī)信息的兩個(gè)關(guān)鍵字查詢函數(shù)是gethostbyname(查找與主機(jī)名匹配的表項(xiàng))和gethostbyaddr(查找與IP地址匹配的表項(xiàng))。表5-2對(duì)此作了總結(jié)。表5-2 四類(lèi)與網(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正在使用時(shí),只有主機(jī)和網(wǎng)絡(luò)信息是通過(guò)DNS提供的,服務(wù)和協(xié)議信息一般要從相應(yīng)的文件中讀。還有一種名字和地址的轉(zhuǎn)換方法是直接調(diào)用解析器函數(shù),而不使用gethostbyn
45、ame和gethostbyaddr。用這種方法來(lái)調(diào)用DNS的一個(gè)程序是sendmail,它搜索MX記錄,這是gethostbyXXX函數(shù)無(wú)法做到的。解析器函數(shù)都有以res_開(kāi)頭的名字。5.5 套接字選項(xiàng)網(wǎng)絡(luò)系統(tǒng)是通過(guò)核心的套接字結(jié)構(gòu)來(lái)實(shí)現(xiàn)對(duì)傳輸層的抽象,系統(tǒng)為用戶提供了獲取和修改套接字結(jié)構(gòu)中一些屬性的函數(shù),通過(guò)修改這些屬性,用戶可以調(diào)整套接字的性能,進(jìn)而調(diào)整用戶編寫(xiě)的網(wǎng)絡(luò)應(yīng)用的性能。有很多方法可以用來(lái)獲取和設(shè)置套接口的選項(xiàng),主要有:l 函數(shù)getsockopt和setsockoptl 函數(shù)fcntll 函數(shù)ioctl5.5.1 獲取和設(shè)置套接口選項(xiàng)系統(tǒng)提供了函數(shù)getsockopt和setso
46、ckopt,分別用于獲取套接口選項(xiàng)和設(shè)置套接口選項(xiàng),這兩個(gè)函數(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是一個(gè)已經(jīng)打開(kāi)的套接口描述符,level是選項(xiàng)的層次,它指定系統(tǒng)中解釋選項(xiàng)的代碼:普通
47、套接口代碼或者特定于協(xié)議的代碼,即通用套接口(SOL_SOCKET)、IP層套接口(IPPROTO_IP)和TCP套接口選項(xiàng)(IPPROTO_TCP)等層次。通用套接口選項(xiàng)一般可適用于TCP/UDP套接口,而TCP套接口選項(xiàng)只適用于TCP套接口。optname是選項(xiàng)的名字。optval是一個(gè)指向變量的指針,用于存放獲取或者設(shè)置的選項(xiàng)值的空間,此變量的大小由最后一個(gè)參數(shù)指定。由于不同的選項(xiàng)的數(shù)據(jù)類(lèi)型不同,因此使用的是void *類(lèi)型的指針。表5-3總結(jié)了可由getsockopt獲取或者由setsockopt設(shè)置的一些選項(xiàng)。表中數(shù)據(jù)類(lèi)型列給出了指針optval必須指向的每個(gè)選項(xiàng)的數(shù)據(jù)類(lèi)型表5-3
48、套接口選項(xiàng)級(jí)別選項(xiàng)名獲取設(shè)置說(shuō)明標(biāo)志數(shù)據(jù)類(lèi)型SOL_SOCKETSO_BROADCAST*允許發(fā)送廣播數(shù)據(jù)報(bào)*intSO_DEBUG*使能調(diào)試跟蹤*intSO_DONTROUTE*不使用路由表尋找路由*intSO_ERROR*獲取待處理錯(cuò)誤并清除intSO_KEEPALIVE*周期地測(cè)試連接是否存活*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*接收超時(shí)struct timevalSO_SNDTIMEO*發(fā)送超時(shí)struct timevalSO_REUSEADDR*允許本地地址重用*intSO_REUSEPORT* 允許端口重用*intSO_TYPE*獲取套接口的類(lèi)型intSO_USELOOPBACK*路由套接口取得所發(fā)送數(shù)據(jù)的拷貝*intIPPROTO_IPIP_HDRINCL*IP頭部包括數(shù)據(jù)*intIP_OPTIONS*IP 頭部選項(xiàng) struct ipoptionIP_RECVDSTADDR*返回目的IP地址*intIP_RECVIF*返回接收到的接口索引*intIP_TOS*服
50、務(wù)類(lèi)型和優(yōu)先權(quán)intIP_TTL*存活時(shí)間intIP_MULTICAST_IF*指定外出接口struct in_addrIP_MULTICAST_TTL*指定外出TTLu_charIP_MULTICAST_LOOP*指定是否回饋u_charIP_ADD_MEMBERSHIP*加入多播組struct ip_mreqIP_DROP_MEMBERSHIP*離開(kāi)多播組struct ip_mreqIPPROTO_ICMPV6ICMP6_FILTER*指定傳遞的ICMPV6消息類(lèi)型struct icmp6_filterIPPROTO_IPV6IPV6_ADDRFORM*改變套接口的地址結(jié)構(gòu)intIPV6_
51、CHECKSUM*原始套接口的校驗(yàn)和字段偏移intIPV6_DSTOPTS*接收目標(biāo)選項(xiàng)*intIPV6_HOPLIMIT*接受單播跳限*intIPV6_HOPOPTS* 接受跳步選項(xiàng)*intIPV6_NEXTHOP*指定下一跳地址*struct sockaddrIPV6_PKTINFO*接收分組信息*intIPV6_PKTOPTIONS*指定分組選項(xiàng)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*離開(kāi)多播組struct ipv6_mreqIPPROTO_TCPTCP_KEEPALIVE*控測(cè)對(duì)方是否存活前連接閑置秒數(shù)intTCP_MAXRT*TCP最大重傳時(shí)間intTCP_MAXSEG*TCP最大分節(jié)大小intTCP_NONDELAY*禁止Nagle算法*intTCP_STDURG*緊急指針的解釋*int有兩種基本類(lèi)型的套接口選項(xiàng):打開(kāi)或者關(guān)閉某個(gè)特性的二進(jìn)制選項(xiàng)(標(biāo)志),取得或者返回用戶可以設(shè)置或檢查的特
53、定值的選項(xiàng)。標(biāo)有“標(biāo)志”的列指明選項(xiàng)是否為標(biāo)志選項(xiàng)。當(dāng)給這些標(biāo)志選項(xiàng)調(diào)用函數(shù)getsockopt時(shí),optval是一個(gè)整數(shù)。optval中返回的值是0表示選項(xiàng)關(guān)閉,非0表示選項(xiàng)打開(kāi)。類(lèi)似地,函數(shù)setsockopt要求一個(gè)非0的optval來(lái)打開(kāi)選項(xiàng),要求用0來(lái)關(guān)閉選項(xiàng)。如果“標(biāo)志”不含有“*”,則選項(xiàng)用來(lái)在用戶進(jìn)程與系統(tǒng)間傳遞指定數(shù)據(jù)類(lèi)型的值。5.5.2 通用套接口選項(xiàng)基本套接口選項(xiàng)是協(xié)議無(wú)關(guān)的,即它們由內(nèi)核中的協(xié)議無(wú)關(guān)代碼處理,而不是由諸如IPv6這樣的一類(lèi)特殊的協(xié)議模塊來(lái)處理。但是這些選項(xiàng)僅能應(yīng)用到某些確定類(lèi)型的套接口中。例如,盡管SO_BROADCAST套接口選項(xiàng)是一個(gè)基本選項(xiàng),但它僅能應(yīng)用于數(shù)據(jù)報(bào)套接口。SO_BROADCAST此選項(xiàng)使能或者禁止套接口發(fā)送廣播消息。在網(wǎng)絡(luò)通信中,如果一個(gè)進(jìn)程需要發(fā)送廣播消息,必須滿足兩個(gè)條件:硬件必須支持廣播,例如以太網(wǎng);必須使用UDP數(shù)據(jù)報(bào)來(lái)發(fā)送廣播消息,TCP套接口不能發(fā)送廣播消息。由于一個(gè)應(yīng)用程序發(fā)送一個(gè)廣播數(shù)據(jù)報(bào)之前必須設(shè)置此套接口,因此它能有效防止該進(jìn)程在應(yīng)用程序未設(shè)計(jì)成能廣播時(shí)就發(fā)送廣播消息。套接口的缺省是禁止廣播信息的發(fā)送。如果UDP程序希望發(fā)送廣播消息,則可以使用下面語(yǔ)句修改設(shè)置。int b_broadcast_on=1;setsoc
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 十二指腸潰瘍的臨床護(hù)理
- 某年春開(kāi)學(xué)典禮教師代表發(fā)言稿模版
- 管理與員工的關(guān)系構(gòu)建策略
- 《血液制品安全管理》課件
- 《腦水腫的護(hù)理與治療》課件
- 2025年供氣合同樣本模板
- 2025深圳短期工勞動(dòng)合同
- 保險(xiǎn)業(yè)務(wù)員2025年上半年工作總結(jié)模版
- 人教版分?jǐn)?shù)的大小比較
- 《青少年心理健康指導(dǎo)》課件
- 破產(chǎn)法試題及答案
- 憲法衛(wèi)士2023第八屆全國(guó)學(xué)生學(xué)憲法講憲法知識(shí)競(jìng)賽題庫(kù)附答案(300題)
- 靜脈輸液不良反應(yīng)及處理 課件
- 河南省開(kāi)封市等2地2025屆高三第三次質(zhì)量檢測(cè)英語(yǔ)+答案
- 北師大版2025三年級(jí)語(yǔ)文下學(xué)期期中課堂知識(shí)檢測(cè)考試
- 2024年甘肅蘭州事業(yè)單位招聘考試真題答案解析
- 寧波浙大寧波理工學(xué)院招聘13名事業(yè)編制工作人員筆試歷年參考題庫(kù)附帶答案詳解
- MOOC 頸肩腰腿痛中醫(yī)防治-暨南大學(xué) 中國(guó)大學(xué)慕課答案
- 維修手冊(cè)震旦218現(xiàn)場(chǎng)
- 畫(huà)法幾何與陰影透視復(fù)習(xí)題(DOC)
- 螺旋密封的設(shè)計(jì)及在流體機(jī)械中的應(yīng)用
評(píng)論
0/150
提交評(píng)論