網絡程序設計教材 名字與地址轉換_第1頁
網絡程序設計教材 名字與地址轉換_第2頁
網絡程序設計教材 名字與地址轉換_第3頁
網絡程序設計教材 名字與地址轉換_第4頁
網絡程序設計教材 名字與地址轉換_第5頁
已閱讀5頁,還剩20頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、第五章 名字與地址轉換5.1 域名系統盡管通過IP地址可以唯一地識別主機上的網絡接口,從而訪問網絡中的每個主機。但是,由于IP地址不便于人們記憶,因此人們還是習慣于使用主機名來訪問網絡。隨著IPv6協議的不斷廣泛應用,數值地址變得更長,手工鍵入一個地址更容易出錯。在大多數操作系統中,任何應用程序都可以調用一個標準的庫函數來查看給定名字的主機的IP地址(UNIX系統中函數名);同樣,系統還提供了一個逆函數,即給定主機的IP地址,查看它所對應的主機名。大多數使用主機名作為參數的應用程序也支持把IP地址作為參數。域名系統DNS(Domain Name System)主要用于主機名與IP地址間的映射。

2、主機名可以是簡單名字,例如Jida,也可以是全限定域名FQDN(Fully Qualified Domain Name),例如。嚴格地說,FQDN也稱為絕對名字(absolute name),因此必須以一個點號結尾,但用戶經常省略最后的點號。在Internet上使用了基于層次型的名字管理機制。在Internet的層次型名字管理中,先由中央管理機構(例如Internet的NIC)將最高一級的名字空間進行劃分,并將相應部分的管理權交給相應的機構,各管理機構可對名字空間進行進一步的劃分。一般來說,最高一級的名字空間的劃分是基于“網絡節點名”(site name)的。網絡節點的概念是對Internet

3、整個網絡的一部分(通常由若干個網絡構成)的一種抽象,這些網絡的組織關系或地理位置聯系非常緊密,可以將它們看成一個節點。各個網絡節點中又可劃分成不同的管理組。組名下面是主機的本地名。典型的Internet層次型主機名由三部分構成:本地名稱.管理組名.網絡節點名例如,其中cn屬于第一級的名字空間,代表國家;第二級域為,代表教育機構,最低一級代表吉林大學。5.1.1 資源記錄在TCP/IP環境中,域名系統(DNS)是一個分布式數據庫系統,通過它來提供IP地址和主機名之間的映射。DNS中的條目稱為資源記錄RR(resource record),僅有少數幾類RR會影響名字與地址轉換。AA記錄將主機名映射

4、為32位的IPv4地址。例如,這里有域中關于主機solaris的四個DNS記錄,其中第一個就是一個A記錄:IN AAAA5f1b:df00:ce3e:e200:0020:0800:2078:e3e3IN MX5 .IN MX10 .AAAAAAAA記錄將主機名映射為128位的IPv6地址。PTRPTR記錄(稱為“指針記錄”)將IP地址映射為主機名。對于IPv4地址,32位地址的四個字節順序反轉,每個字節都轉換成它的十進制ASCII值(0到255),然后附上,結果串用于PTR查詢。對于IPv6地址,128位地址中的32個4位組順序反轉,每組被轉換成相應的十六進制ASCII

5、值(0到9,a到f),并附上.例如,主機solaris的兩個PTR記錄為:06.和3.。MXMX記錄指定一個主機作為某主機的“郵件交換器”。在上面主機的solaris例子中,提供了兩個MX記錄,第一個記錄的優先級是5,第二個記錄的優先級是10,當有多個MX記錄存在時,需按優先級值的順序使用,從最小值開始。CNAMECNAME代表“canonical name(規范名字)”,其常見的用法是為常用服務如

6、WWW和FTP指派一個CNAME記錄。如果用戶使用這些服務名而不是實際上的主機名,則它在服務挪到其它主機上時是透明的。例如,主機Jida的CNAME如下:5.1.2 解析器和名字服務器組織運行一個或多個名字服務器(name server),它們通常就是所說的BIND(Berkeley Internet Name Domain)程序。任何應用程序,通過調用稱為解析器(resolver)的庫中的函數來與DNS服務器聯系。應用程序用來將主機名轉換為IP地址或進行相反過程的一組函數稱為解析器。最常見的解析器函數是gethostbyname和gethostbyaddr,前者將主機名映射為IP地址,后者執

7、行相反的映射。圖5-1說明了應用進程、解析器和名字服務器的典型關系。解析器代碼包含在系統庫中,在構造應用程序時被鏈接到應用程序中。應用程序代碼使用正常的函數調用來調用解析器代碼,最典型的就是調用函數gethostbyname和gethostbyaddr。應用進程應用程序代碼函數返回函數調用UDP請求遠程名字服務器本地名字服務器解析器代碼UDP應答解析器配置文件圖5-1 應用進程、解析器和名字服務器的關系解析器代碼讀其依賴于系統的配置文件來確定組織的名字服務器們的所在位置。文件/etc/resolv.conf一般包含本地名字服務器的IP地址。解析器使用UDP給本地名字服務器發查詢,如果本地名字服

8、務器不知道答案,它也可以使用UDP在整個因特網上給其它名字服務器發查詢。5.1.3 DNS替代方法不使用DNS也可以得到主機的名字和地址信息,最常用的替代方法為靜態主機文件(一般為文件/etc/hosts)或網絡信息系統NIS(Network Information System)。這里需要注意的是,管理員如何配置一個主機來使用不同的名字服務是依賴于不同的實現的,Solaris2.x和HP-UX10.30使用/etc.nsswitch.conf,Digital Unix使用文件/etc/svc.conf,,IBM AIX使用文件/etc/netsvc.conf。BIND8.1提供了自己的名字為

9、信息檢索服務IRS(Information Retrival Service)的版本,它使用文件/etc/irs.conf。如果一個名字服務器將為主機名查找所用,則所有這些系統都使用文件/etc/resolv.conf來指定此名字服務器的IP地址。這些差異一般對應用程序開發人員透明,因此,用戶只需調用gethostbyname和gethostbyaddr這樣的解析器函數就可以了。5.2 gethostbyname函數計算機主機通常以人們可讀的名字被認知,尤其是從IPv4協議向IPv6協議移植時,由于IPv6地址比IPv4地址要長得多,使用名字服務顯得更加正確和重要。查找主機名最基本的函數是ge

10、thostbyname,如果調用成功,它返回一個指向結構hostent的指針,該結構中包含了該主機的所有IPv4地址或IPv6地址。具體使用方法如下:#include <netdb.h>struct hostent *gethostbyname(const char *hostname);此函數返回的非空指針指向下面的hostent結構: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函數執行一個對A記錄的查詢或對AAAA記錄的查詢,它返回IPv4地址或IPv6地址。圖5-2所示為結構hostent和它所指向的各種信

12、息的關系,該圖中被查詢的主機有兩個別名和三個IPv4地址。在這些字段中,正式的主機名和所有的別名都是以空字符(“0”)結尾的C字符串。當返回IPv6地址時,結構hostent的成員h_addrtype被設置為AF_INET6,成員h_length被設置為16。從BIND 4.9.2版本開始,新的gethostbyname版本允許主機名參數是點分十進制數串,即下面調用是可行的: hptr=gethostbyname(“”);gethostbyname函數與其它套接口函數的不同之處在于:當發生錯誤時,它不設置errno,而是將全局整數h_errno設置為定義在頭文件<netdb.h>

13、中的下列常值中的一個:l HOST_NOT_FOUNDl TRY_AGAINl NO_RECOVERYl NO_DATA (等同于NO_ADDRESS)錯誤NO_DATA表示指定的名字有效,但它既沒有A記錄,也沒有AAAA記錄。只有MX記錄 的主機名就是這樣的例子。BIND的當前版本提供函數hstrerror,它將h_errno的值作為唯一的參數,返回一個指向相應錯誤說明的const char *型指針。 正式主機名 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 結構hostent及其包含信息下面程序給出了一個調用gethostbyname函數的例子,它可有任意數目的命令行參數,輸出所有返回的信息。#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、來設置它。用戶可以用此選項來通知解析器想讓gethostbyname返回IPv6地址而不是IPv4地址。具體方法如下:1 應用程序本身可以設置此選項,首先調用解析器的res_init函數,然后打開該選項:#include <resolv.h>res_init();_res.options |= RES_USE_INT6;上面語句必須在第一次調用gethostbyname或gethostbyname2之前完成。此選項僅對那些設置了此選項的應用程序才有效。2 如果環境變量RES_OPTIONS含有串inet6,則此選項打開。此選項的作用依賴于環境變量的范圍。例如,如果用戶在.profi

18、le文件(使用Korn Shell)中以exports屬性設置它,例如:export RES_OPTIONS=inet6則它對從登錄shell開始運行的每個程序都有效。但如果用戶僅在命令行上設置該環境變量,則它僅對那個命令有影響。3 解析器配置文件(一般為/etc/resolv.conf)可以包含如下行:options inet6在解析器配置文件中設置此選項影響主機上調用解析器函數的所有應用程序,因此,這項技術要直到結構hostent中返回的IPv6地址可以被主機上的所有應用程序所處理時才能使用。第一種方法以每個應用程序為基礎設置此選項,第二種方法以每個用戶為基礎,第三種方法以整個系統為基礎。

19、當IPv6支持增加到BIND 4.9.4時,函數gethostbyname2也增加進去,它有兩個參數允許用戶指定地址族。具體使用方法如下:#include <netdb.h>struct hostent * gethostbyname2(const char *hostname, int family);該函數成功時返回非空指針,出錯時返回空指針并設置h_errno值。該函數的返回值與gethostbyname的返回值相同,為一個指向結構hostent的指針,且此結構也保持不變。該函數的邏輯依賴于參數family和解析器選項RES_USE_INET6。對于新選項RES_USE_IN

20、ET6,函數gethostbyname和gethostbyname2的操作:l RES_USE_INET6選項是否打開;l gethostbyname2的第二個參數是AF_INET還是AF_INET6;l 解析器是搜索A記錄還是搜索AAAA記錄;l 返回地址長度是4還是16。函數gethostbyname2的操作如下:l 如果參數family是AF_INET,則查詢A記錄。若不成功,則返回一個空指針,若成功,則返回地址的類型和大小依賴于新的解析器選項RES_USE_INET6:若選項未設置(缺省),則返回IPv4地址,結構hostent的成員h_length的值將為4;若選項設置,則返回IPv

21、4映射的IPv6地址,結構hostent的成員h_length的值將為16。l 如果參數family為AF_INET6,則查詢AAAA記錄。若成功,則返回IPv6地址,結構hostent的成員h_length的值將為16;否則返回一個空指針。表5-1詳細地總結了對于新選項RES_USE_INET6,函數gethostbyname和gethostbyname2的操作。表5-1 解析器選項RES_USE_INET6與函數gethostbyname和gethostbyname2RES_USE_INET6選項關閉打開gethostbyname(host)搜索A記錄,若找到,返回IPv4地址(h_len

22、gth=4),否則返回錯誤。這為現存的IPv4應用程序提供了向后兼容性搜索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),否則返回錯誤如果應用程序想強制某個指定地址類型的搜索:IPv4或IPv6,則可以使用gethostbyname2函數。但對應用程序來說,調用gethostbyname函數似乎更常見,而且該函數的較新版本既可以返回IPv4地址,也可以返回IPv6地址。如果解析器沒有被初始化(沒有設置標志RES_INIT),則調用res_init。此初始化函數檢查并處理環境變量RES_OPTIONS。如果這個變量包含串inet6或如果解析器配置文件包含行options inet6,則標志RES_USE_INET6由res_init設置。res_

24、init一般由函數gethostbyname或gethostbyaddr在第一次被應用程序調用時自動調用的。此外,應用程序也可以調用res_init,然后顯式設置標志RES_USE_INET6。總之,當選項RES_USE_INET6打開且應用程序調用gethostbyname時,應用程序通知解析器:返回IPv6地址,首先搜索AAAA記錄,如果未找到則搜索A記錄,如果A記錄找到則返回IPv4映射的IPv6地址。5.4 與名字和地址有關的常用函數5.4.1 gethostbyaddr函數函數gethostbyaddr取一個二進制的IP地址并試圖找到相應的主機名,此函數與gethostbyname的

25、功能相反。gethostbyaddr返回一個指向結構hostent的指針。具體使用方法如下:#include <netdb.h>struct hostent *gethostbyaddr(const char *addr, size_t len, int family);參數addr是一個真正指向含有IPv4或IPv6地址的結構in_addr或in6_addr的指針;len是此結構的大小:對于IPv4地址為4,對于IPv6地址為16;參數family或者是AF_INET或者是AF_INET6。按照DNS原理,gethostbyaddr在域in_中給IPv4地址在名

26、字服務員上查詢PTR記錄,或在域中給IPv6地址查詢PTR記錄。gethostbyaddr總有一個地址族參數,所以當加上IPv6支持到BIND時,無需另一個函數(類似于函數gethostbyname2)。但是,當參數是IPv6地址時,仍有一些差別。下面的判斷按步驟進行: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地址(或參數family為AF_INET,或上述兩種情況中的一個為真)且解析器選項RES_USE_INET6設置,則返回的地址(參數addr的一個拷貝)被轉換為一個IPv4映射的IPv6地址:h_addrtype為AF_INET6,h_length為16。5.4.2 uname函數函數uname返回當前主機的名字。它雖然不是解析器庫中的一部分,但它經常與函數gethostbyname一起用來確定本地主機的IP地址。具體使用方法如下:#include <sys/utsname.h>int uname(struct ustname *name);該函數調

28、用成功時返回一個非負整數,發生錯誤時返回-1。此函數裝填結構utsname,其地址由調用者傳遞:#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所規定的只是上面的五個結構成員的名字以及每個數組是一個以空字符(“0”)終止的字符數組,對于每個數組的大小及內容并未作任何說明。上面給出的大小來源于4.4BSD,其它操作系統采用不同的大小。從網絡程序設計角度來看,最嚴重的忽略是對數組nodename大小和內容的定義。有些系統僅在此數組中存儲主機名(例如Jida),而另外一些系統存儲FQDN(例如J)。在有些操作系統如Solaris2.x上,既可以存放主機名,也可以存放FQDN,主要取決于管理員是

30、如何安裝操作系統的。為了確定本地主機的IP地址,用戶可以調用uname函數以得到主機名字,然后調用gethostbyname函數以得到它的所有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);上述函數返回值是結構hostent的成員h_addr_list,即指向IP地址的指針數組。確定本地主機IP地址的另一種方法是ioctl的命令SIOCGIFCONF。5.4.3 gethostname函數函數gethostname的功能也是返回當前主機的名字。具體使用方法如下:#include <unistd.h>int gethostname(char *name, size_t namelen);name是指向主機名存儲位

32、置的在指針,namelen是此數組的大小。如果有空間,主機名以空字符結束。主機名的最大值通常是由頭文件<sys/param.h>定義的常值MAXHOSTNAMELEN。從歷史上看,uname由系統V定義,而gethostbyname由Berkeley定義。Posix.1 指定uname,但Unix 98兩者都支持。5.4.4 getservbyname和getservbyport函數服務器也常常由名字來標識。如果在代碼中,通過服務器的名字而不是通過服務器端口號來認知它,而且如果從主機到端口號的映射包含在一個文件中(通常是/etc/services),則如果端口號改變,用戶所需要做的

33、修改就是改動/etc/services文件中的一行,而不需要重新編譯應用程序。getservbyname函數可以根據給定的名字查找相應的服務,具體使用方法如下:#include <netdb.h>struct servent * getservbyname(const char *servname, const char *protoname);該函數調用出錯時返回空指針,成功時返回非空指針,返回一個指向下面所示結構的指針: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*/;服務器名字servname必須指定,如果還指定了一個協議,則結果表項也必須有匹配的協議。有些因特網服務既可使用UDP協議,又可以使用TCP協議,例如NFS(網絡文件系統);而其它一些服務則僅支持單個協議。如果protoname沒有指定且支持多個協議,則返回哪個端口是依賴于具體實現的。一般來說,支持多個協議的服務常常使用相同的TCP和UDP端口號。結構servent中主要成員是端口號。由于端口號是以網絡字節順序返回的。

35、在將它存儲于套接口地址結構時,絕對不能調用htons函數。對此函數的典型調用是: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,所以第二個調用和第三個

36、調用的結果是相同的,第四個調用將失敗。下面是關于文件/etc/services中的內容:ftp 21/tcp telnet 23/tcp tftp 69/udp login 513/tcp函數getservbyport在給定斷口號和可選協議后查找相應的服務。具體使用方法如下:#include <netdb.h>struct servent * getservbyport(int port, const char *protoname);port值必須為網絡字節順序。對此函數的典型調用是: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,由于沒有服務使用端口21,所以最后一個調用將失敗。這里用戶需要清楚,有些端口對于TCP可能用于一種服務,但對于UDP,同樣的端口號也完全可能用于不同的服務。下面代碼是使用gethostbyna

38、me和getservbyname函數實現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 其它網

42、絡相關信息本章的重點在于主機名與IP地址、服務名與端口號。其實應用程序可能需要查詢和網絡相關的四種類型信息:主機、網絡、協議與服務。大多數查詢都是針對主機的(gethostbyname和gethostbyaddr),有一小部分是針對網絡服務的(getservbyname和getservbyport),針對網絡和協議的查詢就更少了。所有四類信息都可以存儲在文件中,而且每類信息都定義三個函數:1. 函數getXXXent讀文件中的下一表項,在必要時可以打開文件。2. 函數setXXXent打開(如果文件沒有打開)并回繞文件。3. 函數endXXXent關閉文件。每類信息都定義了自己的結構,這些定義

43、包含在<netdb.h>中:hostent、netent、protoent和servent結構。除了三個用于文件的順序處理的get、set和end函數外,每類信息還提供了一些鍵值查詢(keyed lookup)函數。它們順序瀏覽文件(調用函數getXXXent來讀每一行),但不返回每一行給調用者,而是查找一個與某參數匹配的表項。這些鍵值查詢函數的名字類似函數getXXXbyYYY。例如,針對主機信息的兩個關鍵字查詢函數是gethostbyname(查找與主機名匹配的表項)和gethostbyaddr(查找與IP地址匹配的表項)。表5-2對此作了總結。表5-2 四類與網絡相關的信息信

44、息數據文件結構鍵值搜索函數主機/etc/hostshostentgethostbyaddr, gethostbyname網絡/etc/networksnetentgetnetbyaddr, getnetbyname協議/etc/protocolsprotoentgetprotobyname, getprotobynumber服務/etc/servicesserventgetservbyname, getservbyport當DNS正在使用時,只有主機和網絡信息是通過DNS提供的,服務和協議信息一般要從相應的文件中讀。還有一種名字和地址的轉換方法是直接調用解析器函數,而不使用gethostbyn

45、ame和gethostbyaddr。用這種方法來調用DNS的一個程序是sendmail,它搜索MX記錄,這是gethostbyXXX函數無法做到的。解析器函數都有以res_開頭的名字。5.5 套接字選項網絡系統是通過核心的套接字結構來實現對傳輸層的抽象,系統為用戶提供了獲取和修改套接字結構中一些屬性的函數,通過修改這些屬性,用戶可以調整套接字的性能,進而調整用戶編寫的網絡應用的性能。有很多方法可以用來獲取和設置套接口的選項,主要有:l 函數getsockopt和setsockoptl 函數fcntll 函數ioctl5.5.1 獲取和設置套接口選項系統提供了函數getsockopt和setso

46、ckopt,分別用于獲取套接口選項和設置套接口選項,這兩個函數僅用于套接口。具體使用方法如下:#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是一個已經打開的套接口描述符,level是選項的層次,它指定系統中解釋選項的代碼:普通

47、套接口代碼或者特定于協議的代碼,即通用套接口(SOL_SOCKET)、IP層套接口(IPPROTO_IP)和TCP套接口選項(IPPROTO_TCP)等層次。通用套接口選項一般可適用于TCP/UDP套接口,而TCP套接口選項只適用于TCP套接口。optname是選項的名字。optval是一個指向變量的指針,用于存放獲取或者設置的選項值的空間,此變量的大小由最后一個參數指定。由于不同的選項的數據類型不同,因此使用的是void *類型的指針。表5-3總結了可由getsockopt獲取或者由setsockopt設置的一些選項。表中數據類型列給出了指針optval必須指向的每個選項的數據類型表5-3

48、套接口選項級別選項名獲取設置說明標志數據類型SOL_SOCKETSO_BROADCAST*允許發送廣播數據報*intSO_DEBUG*使能調試跟蹤*intSO_DONTROUTE*不使用路由表尋找路由*intSO_ERROR*獲取待處理錯誤并清除intSO_KEEPALIVE*周期地測試連接是否存活*intSO_LINGER*若有數據待發送則延遲關閉struct lingerSO_OOBINLINE*讓接收到的帶外數據繼續在線存放*intSO_RCVBUF*接收緩沖區大小intSO_SNDBUF*發送緩沖區大小intSO_RCVLOWAT* 接收緩沖區的下限指示intSO_SNDLOWAT*發

49、送緩沖區的下限指示intSO_RCVTIMEO*接收超時struct timevalSO_SNDTIMEO*發送超時struct timevalSO_REUSEADDR*允許本地地址重用*intSO_REUSEPORT* 允許端口重用*intSO_TYPE*獲取套接口的類型intSO_USELOOPBACK*路由套接口取得所發送數據的拷貝*intIPPROTO_IPIP_HDRINCL*IP頭部包括數據*intIP_OPTIONS*IP 頭部選項 struct ipoptionIP_RECVDSTADDR*返回目的IP地址*intIP_RECVIF*返回接收到的接口索引*intIP_TOS*服

50、務類型和優先權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*改變套接口的地址結構intIPV6_

51、CHECKSUM*原始套接口的校驗和字段偏移intIPV6_DSTOPTS*接收目標選項*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*控測對方是否存活前連接閑置秒數intTCP_MAXRT*TCP最大重傳時間intTCP_MAXSEG*TCP最大分節大小intTCP_NONDELAY*禁止Nagle算法*intTCP_STDURG*緊急指針的解釋*int有兩種基本類型的套接口選項:打開或者關閉某個特性的二進制選項(標志),取得或者返回用戶可以設置或檢查的特

53、定值的選項。標有“標志”的列指明選項是否為標志選項。當給這些標志選項調用函數getsockopt時,optval是一個整數。optval中返回的值是0表示選項關閉,非0表示選項打開。類似地,函數setsockopt要求一個非0的optval來打開選項,要求用0來關閉選項。如果“標志”不含有“*”,則選項用來在用戶進程與系統間傳遞指定數據類型的值。5.5.2 通用套接口選項基本套接口選項是協議無關的,即它們由內核中的協議無關代碼處理,而不是由諸如IPv6這樣的一類特殊的協議模塊來處理。但是這些選項僅能應用到某些確定類型的套接口中。例如,盡管SO_BROADCAST套接口選項是一個基本選項,但它僅能應用于數據報套接口。SO_BROADCAST此選項使能或者禁止套接口發送廣播消息。在網絡通信中,如果一個進程需要發送廣播消息,必須滿足兩個條件:硬件必須支持廣播,例如以太網;必須使用UDP數據報來發送廣播消息,TCP套接口不能發送廣播消息。由于一個應用程序發送一個廣播數據報之前必須設置此套接口,因此它能有效防止該進程在應用程序未設計成能廣播時就發送廣播消息。套接口的缺省是禁止廣播信息的發送。如果UDP程序希望發送廣播消息,則可以使用下面語句修改設置。int b_broadcast_on=1;setsoc

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論