网络程序设计教材 名字与地址转换_第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

提交评论