第06章名字與地址轉(zhuǎn)換編程_第1頁
第06章名字與地址轉(zhuǎn)換編程_第2頁
第06章名字與地址轉(zhuǎn)換編程_第3頁
第06章名字與地址轉(zhuǎn)換編程_第4頁
第06章名字與地址轉(zhuǎn)換編程_第5頁
已閱讀5頁,還剩48頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第6章

名字與地址轉(zhuǎn)換編程知識點(diǎn):

域名系統(tǒng)作用域名系統(tǒng)對應(yīng)記錄從域名解析對應(yīng)IP從IP解析對應(yīng)域名現(xiàn)在的網(wǎng)絡(luò)都是使用名字來訪問服務(wù)器的,而不是使用地址來訪問。那它們是怎么轉(zhuǎn)換的呢?答案就是利用名字與地址的轉(zhuǎn)換函數(shù)實(shí)現(xiàn)的:gethostbyname和gethostbyaddr在主機(jī)名字與IP地址間進(jìn)行轉(zhuǎn)換,getservbyname和getservbyport在服務(wù)名字和端口號間進(jìn)行轉(zhuǎn)換,并且還要介紹兩個(gè)與協(xié)議無關(guān)的getaddrinfo和getnameinfo函數(shù)域名系統(tǒng)就是通常所說的DNS(DomainNameSystem)系統(tǒng),而DNS系統(tǒng)主要用于主機(jī)名與IP地址間的映射,同時(shí)還可以通過主機(jī)名或主機(jī)地址獲取主機(jī)的相關(guān)信息。那么在DNS系統(tǒng)中是怎樣實(shí)現(xiàn)主機(jī)名與IP地址間的映射的呢?答案就是通過資源記錄來實(shí)現(xiàn)。在DNS中的條目稱為資源記錄RR(ResourceRecord),它們主要有以下幾類:(1)A。A記錄將一個(gè)域名地址對應(yīng)一個(gè)32bit的IPv4地址。(2)AAAA。AAAA記錄(稱為“四A”記錄)將主機(jī)名映射為128位的IPv6地址。(3)NS。NS記錄用于指定一個(gè)域名服務(wù)器,它負(fù)責(zé)定義由哪個(gè)域名服務(wù)器負(fù)責(zé)管理維護(hù)本區(qū)域的記錄。(4)MX.MX記錄用于指定一臺主機(jī)的域名,所有發(fā)送到本域的電子郵件都由這臺主機(jī)接收。(5)PTR。PTR記錄(稱為“指針記錄”)將IP地址映射為主機(jī)名。(6)CNAME。CNAME代表CanonicalName(規(guī)范名字),作用是允許主機(jī)建立別名。名字解析過程應(yīng)用程序代碼解析器代碼解析器配置文件函數(shù)調(diào)用函數(shù)返回本地名字服務(wù)器其他名字服務(wù)器UDP請求UDP應(yīng)答應(yīng)用進(jìn)程gethostbyname()函數(shù)找主機(jī)名最基本的函數(shù)gethostbyname(),該函數(shù)執(zhí)行如果成功,它返回一個(gè)指向結(jié)構(gòu)hostent的指針,該結(jié)構(gòu)中包含了該主機(jī)的所有IPv4地址或IPv6地址;如果失敗返回空指針。#include<netdb.h> structhostent*gethostbyname(constchar*hostname);參數(shù)hostname是主機(jī)的域名地址,函數(shù)將查詢的結(jié)果作為參數(shù)返回。如果失敗返回空指針;如果成功此參數(shù)返回的非空指針指向如下的hostent結(jié)構(gòu):結(jié)構(gòu)hostentstructhostent { char*h_name; /*主機(jī)的正式名稱*/ char**h_aliases; /*主機(jī)的別名列表*/ int h_addrtype; /*主機(jī)地址類型*/ int h_length;

/*主機(jī)地址長度*/ char**h_addr_list; *主機(jī)IP地址的列表*/ };#defineh_addrh_addr_list[0] /*在列表中的第一個(gè)地址*/gethostbyname返回的信息h_nameh_aliasesh_addrtypeh_lengthh_addr_listhostent{}正式主機(jī)名\0別名1\0別名2\0IP地址1IP地址2IP地址3NULLNULLAF_INETin_addr{}in_addr{}in_addr{}gethostbyname()函數(shù)是怎樣工作的原來gethostbyname函數(shù)首先在/etc/hosts文件中查找是否有匹配的主機(jī)名。如果沒有,則根據(jù)在域名解析配置文件/etc/resolv.conf中指定的本地域名服務(wù)器的地址向本地域名服務(wù)器發(fā)送地址解析請求。如果本地域名服務(wù)器能夠解析,則返回UDP數(shù)據(jù)包說明結(jié)果,否則本地域名服務(wù)器將向上一層的域名服務(wù)器發(fā)送域名解析請求。下面舉個(gè)例子來看看gethostbyname()函數(shù)#include<netinet/in.h>#include<arpa/inet.h>#include<netdb.h>

main(intargc,constchar**argv){ulong_taddr;structhostent*hp;char**p;if(argc!=2){(void)printf("usage:%shost_name\n",argv[0]);exit(1);}hp=gethostbyname(argv[1]);if(hp==NULL){(void)printf("hostinformationfor%snotfound\n",argv[1]);exit(2);}for(p=hp->h_addr_list;*p!=0;p++){structin_addrin;char**q;(void)memcpy(&in.s_addr,*p,sizeof(in.s_addr));(void)printf("%s\t%s",inet_ntoa(in),hp->h_name);for(q=hp->h_aliases;*q!=0;q++)(void)printf("%s",*q);(void)putchar('\n');}exit(0);}RES_USE_INET6解析器選項(xiàng)解析器選項(xiàng)是用來通知解析器讓gethostbyname返回的是IPv6地址而不是IPv4地址。設(shè)置該選項(xiàng)的方法有以下3種:(1)應(yīng)用程序可以設(shè)置此選項(xiàng)(2)如果環(huán)境變量RES_OPTIONS中含有串inet6,則此選項(xiàng)打開(3)在配置文件中如果包含“optionsinet6”時(shí)選項(xiàng)打開,但如果這樣設(shè)置了,則此選項(xiàng)影響主機(jī)上調(diào)用解析器函數(shù)的所有應(yīng)用程序,因此這項(xiàng)技術(shù)要在結(jié)構(gòu)hostent中返回的IPv6地址可以被主機(jī)上的所有應(yīng)用程序處理時(shí)才能使用。gethostbyname2函數(shù)對IPv6的支持gethostbyname2()函數(shù),該函數(shù)有兩個(gè)參數(shù),并允許指定地址族。#include<netdb.h>structhostent*gethostbyname2(constchar*hostname,intfamily)返回:若為非空指針,則表示成功;若為空指針,則表示出錯(cuò),同時(shí)設(shè)置h_errno。該函數(shù)的返回值與gethostbyname的返回值相同,為一個(gè)指向結(jié)構(gòu)hostent的指針。該函數(shù)的邏輯依賴于參數(shù)family和解析器選項(xiàng)RES_USE_INET6反向域名解析函數(shù)gethostbyaddr()gethostbyaddr()函數(shù)的作用是可以查詢指定的IP地址對應(yīng)的主機(jī)域名地址。函數(shù)的形式如下:#include<netdb.h>structhostent*gethostbyaddr(constchar*addr,size_tlen,intfamily);返回:若為非空指針,則表示成功;若為空指針,則表示出錯(cuò),同時(shí)設(shè)置h_errno。該函數(shù)同樣返回一個(gè)指向結(jié)構(gòu)hostent的指針。而在參數(shù)中,參數(shù)addr不是char*類型,而是一個(gè)真正指向含有IPv4或IPv6地址的結(jié)構(gòu)in_addr或in6_addr的指針;len是此結(jié)構(gòu)的大小,對于IPv4地址為4,對于IPv6地址為16;參數(shù)family為AF_INET或AF_INET6。main(intargc,constchar**argv){ulong_taddr;structhostent*hp;char**p;if(argc!=2){printf("usage:%sIP-address\n",argv[0]);exit(1);}if(((addr=inet_addr(argv[1]))==-1){printf("IP-addressmustbeoftheforma.b.c.d\n");exit(1);}hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);if(hp==NULL){printf("hostinformationfor%snotfound\n",argv[1]);exit(1);}for(p=hp->h_addr_list;*p!=0;p++){structin_addrin;char**q;memcpy(&in.s_addr,*p,sizeof(in.s_addr));printf("%s\t%s",inet_ntoa(in),hp->h_name);for(q=hp->h_aliases;*q!=0;q++)printf("%s",*q);}exit(0);}[root@localhosttest]#./blocalhost.localdomainlocalhost地址轉(zhuǎn)換例子#include<netdb.h>#include<stdio.h>#include<stdlib.h>#include<sys/socket.h>#include<netinet/in.h>intmain(intargc,char*argv[]){structsockaddr_inaddr;structhostent*he;char**alias;if(argc<2){printf("Usage:%sname|IP",argv[0]);exit(1);}地址轉(zhuǎn)換例子(cont.)

argv++;for(;*argv!=NULL;argv++){if(inet_aton(*argv,&addr.sin_addr)!=0){he=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);printf("addressinformationofIP%s:\n",*argv);}else{he=gethostbyname(*argv);printf("addressinformationofhost%s:\n",*argv);}if(he==NULL){printf("noaddressinformationof%s\n",*argv);continue;}地址轉(zhuǎn)換例子(cont.)

printf("Officaialhostname:%s\n",he->h_name);printf("namealiases:");for(alias=he->h_aliases;*alias!=NULL;alias++)printf("%s\n",*alias);printf("\nIPaddresses:");for(alias=he->h_addr_list;*alias!=NULL;alias++)printf("%s\n",inet_ntoa(*(structin_addr*)(*alias)));}}uname()函數(shù)該函數(shù)功能如同它的名字一樣,即返回當(dāng)前主機(jī)的名字,它返回的信息比較完整。下一節(jié)將介紹返回主機(jī)名字的另一個(gè)函數(shù),但它返回的信息就相對少些。經(jīng)常與函數(shù)gethostbyname()一起用來確定本地主機(jī)的IP地址。它的具體形式如下:#include<sys/utsname.h> intuname(structutsname*name);返回:若為非負(fù)值,則表示成功;若為-1,則表示出錯(cuò)。uname函數(shù)該函數(shù)返回本機(jī)的名字,它不是解析器庫中的一部分,但它經(jīng)常與gethostbyname函數(shù)一起用來確定本地主機(jī)IP地址;函數(shù)的參數(shù)是“值-結(jié)果”參數(shù),其類型如下:#defineUTS_NAMESIZE 16#defineUTS_NODESIZE 256structutsname{ charsysname[UTS_NAMESIZE]; /*nameofthisoperatingsystem*/ charnodename[UTS_NODESIZE]; /*主機(jī)的名字*/ charrelease[UTS_NAMESIZE]; /*O.S內(nèi)部版本*/ charversion[UTS_NAMESIZE]; /*O.S發(fā)行版本號*/ charmachine[UTS_NAMESIZE]; /*硬件版本*/}獲取本機(jī)IP地址#include<netdb.h>#include<sys/utsname.h>#include<netinet/in.h>#include<stdio.h>intmain(void){structhostent*he;structutsnamemyname;structin_addraddr;chartemp[100];if(uname(&myname)<0)return(0);獲取本機(jī)IP地址(續(xù))

if((he=gethostbyname(myname.nodename))==NULL){perror("error.");exit(1);}printf("OSnameis%s\n",myname.sysname);printf("nodenameis%s\n",myname.nodename);printf("OSversionreleaseis%s\n",myname.release);printf(“hardwareversionis%s\n”,myname.version);printf("hardwaretypeis%s\n",myname.machine);memcpy(&addr,he->h_addr,sizeof(addr));printf("hostIPis%s\n",inet_ntoa(addr));return(0);}gethostname函數(shù)該函數(shù)同樣返回當(dāng)前主機(jī)的名字,但返回信息比上節(jié)介紹的函數(shù)少,該函數(shù)形式如下:#include<unistd.h>int gethostname(char*name,size_tnamelen);返回:若為0,則表示成功;若為-1,則表示出錯(cuò)。name是指向主機(jī)名存儲(chǔ)位置的指針,namelen是此數(shù)組的大小。如果有空間,主機(jī)名以空字符結(jié)束。主機(jī)名的最大長度通常是由頭文件<sys/param.h>定義的常值MAXHOSTNAMELEN。#include<unistd.h>intmain(){charbuf[100];size_tnamelen;namelen=sizeof(buf);gethostname(buf,namelen);printf("hostnameis%s\n",buf);}getservbyname和getservbyport函數(shù)函數(shù)getservbyname()可以通過服務(wù)名來獲取服務(wù)器端口號,函數(shù)的形式如下:#include<netdb.h>structservent*getservbyname(constchar*servname,constchar*protoname);返回:若為非空指針,則表示成功;若為空指針,則表示出錯(cuò)。函數(shù)是getservbyport()函數(shù),該函數(shù)的作用是通過端口號來獲取服務(wù)名,它是反向的查詢服務(wù)名稱,即功能與getservbyname()函數(shù)相反。下面就來看一下它的具體形式:#include<netdb.h>structservent*getservbyport(intport,constchar*protname);返回:若為非空指針,則表示成功;若為空指針,則表示出錯(cuò)。獲取服務(wù)名字函數(shù)該函數(shù)根據(jù)服務(wù)器提供的服務(wù)名字獲取服務(wù)器的有關(guān)信息;在/etc/services文件中查找。參數(shù)servname指向服務(wù)的名字,如”domain”,”ftp”,”www”;函數(shù)返回的結(jié)構(gòu)如下:structservent{ char *s_name; /*officialservicename*/ char **s_aliases; /*aliaslist*/ int s_port; /*portnumber,net-byteorder*/ char *s_proto; /*protocoltouse*/}如:structservent*ptr;sptr=getservbyname(“FTP”,“TCP”);#include<netdb.h>intmain(){structservent*ptr;ptr=getservbyname("ssh",NULL);if(ptr==NULL){perror("error");exit(0);}printf("portis:%d",ntohs(ptr->s_port));}獲取服務(wù)名字函數(shù)(cont.)#include<netdb.h>structservent*getservbyport(intport,constchar*protoname);

返回:非空指針-成功;空指針-出錯(cuò)。該函數(shù)根據(jù)端口號和可選的協(xié)議查找相應(yīng)的服務(wù);參數(shù)port必須為網(wǎng)絡(luò)字節(jié)序;如:structservent*sptr;sptr=getservbyport(htons(53),“UDP); /*DNSusingUDP*/sptr=getservbyport(htons(21),“TCP”); /*FTPusingTCP*/sptr=getservbyport(htons(21),NULL); /*FTPusingTCP*/sptr=getservbyport(htons(21),”UDP”); /*thiscallwillfail*/#include<netdb.h>#include<errno.h>#include<stdio.h>intmain(){structservent*srv;inti;for(i=1;i<100;i++){srv=getservbyport(htons(i),NULL);if(srv==NULL){printf("PORT%dnoservice\n",i);}elseprintf("PORT:%dservice:%s\n",i,srv->s_name);}}獲取套接字的地址信息#include<sys/socket.h>intgetsockname(intsockfd,structsockaddr*localaddr,socklen_t*len);intgetpeername(intsockfd,structsockaddr*peeraddr,socklen_t*len);

均返回:0-成功;-1-出錯(cuò)getsockname函數(shù)返回套接字的本地地址;而后者返回套接字對應(yīng)的遠(yuǎn)程地址;一般在以下三中情況下調(diào)用這兩個(gè)函數(shù):客戶機(jī)在connect后,用getsockname獲取系統(tǒng)選擇的ip和端口號;以INADDR_ANY調(diào)用bind的服務(wù)器,在接收到連接后(即accept后),調(diào)用getsockname獲取系統(tǒng)選擇的IP地址;服務(wù)器獲得連接后,并exec真正的程序后。只能用getpeername獲取客戶套接字地址;getaddrinfo、gai_strerror和host_serv函數(shù)getaddrinfo()函數(shù)在庫函數(shù)中隱藏了所有協(xié)議依賴性,因此應(yīng)用程序只需要處理由getaddrinfo填寫的套接口地址結(jié)構(gòu)即可。該函數(shù)的形式如下:#include<netdb.h>intgetaddrinfo(constchar*hostname,constchar*service,conststructaddrinfo*hints,structaddrinfo**result);返回:若成功返回0,若出錯(cuò)返回非0。getaddrinfo函數(shù)ai_family指定了地址族,可取值如下:

AF_INET

2

IPv4

AF_INET6

23

IPv6

AF_UNSPEC

0

協(xié)議無關(guān)#ai_socktype指定套接字的類型

SOCK_STREAM

1

SOCK_DGRAM

2

數(shù)據(jù)報(bào)在AF_INET通信域中套接字類型SOCK_STREAM的默認(rèn)協(xié)議是TCP(傳輸控制協(xié)議)

在AF_INET通信域中套接字類型SOCK_DGRAM的默認(rèn)協(xié)議是UDP(用戶數(shù)據(jù)報(bào)協(xié)議)getaddrinfo函數(shù)ai_flags指定了如何來處理地址和名字,可取值如下:

gai_strerror()函數(shù),該函數(shù)返回的非零錯(cuò)誤值的名字和含義如表6-2所示。gai_strerror()函數(shù)以這些值作為它的一個(gè)參數(shù),返回指向?qū)?yīng)的出錯(cuò)信息字符串的指針。該函數(shù)形式如下:# include<netdb.h> char*gai_strerror(interror);返回:一個(gè)指向描述出錯(cuò)信息字符串的指針。填寫hints結(jié)構(gòu)的函數(shù),即host_serv()函數(shù),它以地址族和套接口類型作為參數(shù),形式如下:#include"unp.h"structaddrinfo*host_serv(constchar*hostname,constchar*service,int

family,intsocktype);返回:若成功返回指向addrinfo結(jié)構(gòu)的指針,若出錯(cuò)返回NULL。freeaddrinfo函數(shù)getaddrinfo()函數(shù)返回的存儲(chǔ)空間,包括addrinfo結(jié)構(gòu)、ai_addr結(jié)構(gòu)和ai_canonname字符串,都是用malloc動(dòng)態(tài)獲取的。這些空間可調(diào)用freeadddrinfo()函數(shù)釋放。下面就來看一下這個(gè)函數(shù)。#include<netdb.H>voidfreeaddrinfo(structaddrinfo*ai);該函數(shù)的參數(shù)ai指向getaddrinfo返回的第一個(gè)addrinfo結(jié)構(gòu),因此該鏈表中的所有結(jié)構(gòu)和這些結(jié)構(gòu)所指向的動(dòng)態(tài)存儲(chǔ)空間都將被釋放。這樣可以通過它來回收資源,同時(shí)如果在getaddrinfo()函數(shù)中調(diào)用某個(gè)操作時(shí)失敗,也可以調(diào)用freeaddrinfo()函數(shù)來對錯(cuò)誤進(jìn)行處理。使用getaddrinfo的TCP和UDP有了host_serv()函數(shù)后,現(xiàn)在來看一下getaddrinfo在TCP中的應(yīng)用,先從tcp_connect()函數(shù)著手,該函數(shù)執(zhí)行客戶程序的一般操作步驟是:創(chuàng)建一個(gè)TCP套接口并與服務(wù)器建立連接,它的形式如下:#include"unp.h"inttcp_connect(constchar*hostname,constchar*service);返回:若成功則返回已連接套接口的描述字,若出錯(cuò)則不返回。#include"unp.h"

inttcp_connect(constchar*host,constchar*serv){intsockfd,n;structaddrinfohints,*res,*ressave;bzero(&hints,sizeof(structaddrinfo));hints.ai_family=AF_UNSPEC;hints.ai_socktype=SOCK_STREAM;if((n=getaddrinfo(host,serv,&hints,&res))!=0)err_quit("tcp_connecterrorfor%s,%s:%s",host,serv,gai_strerror(n));ressave=res;do{sockfd=socket(res->ai_family,res->ai_socktype,res->ai_protocol);if(sockfd<0)continue; /*ignorethisone*/if(connect(sockfd,res->ai_addr,res->ai_addrlen)==0)break; /*success*/Close(sockfd); /*ignorethisone*/}while((res=res->ai_next)!=NULL);if(res==NULL) /*errnosetfromfinalconnect()*/err_sys("tcp_connecterrorfor%s,%s",host,serv);freeaddrinfo(ressave);return(sockfd);}當(dāng)用此函數(shù)時(shí)如果getaddrinfo()失敗,或所有connect()失敗,這個(gè)函數(shù)(以及在以下描述的給getaddrinfo()提供一些簡單接口的其他函數(shù))將終止。只有在成功時(shí)這個(gè)函數(shù)才返回。接下來看一下另一個(gè)函數(shù)tcp_listen(),它是用來執(zhí)行TCP服務(wù)器程序的一般操作步驟,即創(chuàng)建一個(gè)TCP套接口,給它捆綁服務(wù)器的眾所周知端口,并允許接收外來的連接請求,該函數(shù)形式如下:#include"unp.H"inttcp_listen(constchar*hostname,constchar*service,socklen_t*lenptr);返回:若成功返回已連接套接口描述字,若出錯(cuò)則不返回。#include"unp.h"

inttcp_listen(constchar*host,constchar*serv,socklen_t*addrlenp){intlistenfd,n;constinton=1;structaddrinfo hints,*res,*ressave;bzero(&hints,sizeof(structaddrinfo));hints.ai_flags=AI_PASSIVE;hints.ai_family=AF_UNSPEC;hints.ai_socktype=SOCK_STREAM;if((n=getaddrinfo(host,serv,&hints,&res))!=0)err_quit("tcp_listenerrorfor%s,%s:%s",host,serv,gai_strerror(n));ressave=res;do{listenfd=socket(res->ai_family,res->ai_socktype,res->ai_protocol);if(listenfd<0) continue; /*error,trynextone*/Setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));if(bind(listenfd,res->ai_addr,res->ai_addrlen)==0)break; /*success*/Close(listenfd); /*binderror,closeandtrynextone*/}while((res=res->ai_next)!=NULL);if(res==NULL) /*errnofromfinalsocket()orbind()*/err_sys("tcp_listenerrorfor%s,%s",host,serv);Listen(listenfd,LISTENQ);if(addrlenp)*addrlenp=res->ai_addrlen; /*returnsizeofprotocoladdress*/freeaddrinfo(ressave);return(listenfd);}到現(xiàn)在為止,已用以上兩個(gè)函數(shù)的源碼介紹了getaddrinfo()函數(shù)在TCP中的一些應(yīng)用,這將對理解getaddrinfo()函數(shù)有很大的幫助,但是這是在TCP中的應(yīng)用,那么在UDP中又是怎樣的情況呢?同樣分別通過udp_client()、udp_connect()、udp_server()三個(gè)函數(shù)來解答這個(gè)問題。因?yàn)樘峁┝艘粋€(gè)創(chuàng)建未連接UDP套接口的客戶函數(shù)給getaddrinfo(),所以在UDP中g(shù)etaddrinfo()函數(shù)的應(yīng)用有所改變。而另一個(gè)函數(shù)udp_connect()則提供一個(gè)創(chuàng)建已連接UDP的套接口。首先來看一下udp_client()函數(shù),該函數(shù)的作用是創(chuàng)建一個(gè)未連接UDP套接口,返回3項(xiàng)數(shù)據(jù):第一,返回值是套接口描述字;第二,saptr是一個(gè)指向套接口地址結(jié)構(gòu)(由udp_client動(dòng)態(tài)分配)的指針(由調(diào)用者聲明)的地址,在這個(gè)結(jié)構(gòu)中存放目的IP地址和端口號,用來調(diào)用sendto(),套接口地址結(jié)構(gòu)的大小在1enp指向的變量中返回;最后一個(gè)參數(shù)不能是空指針(tcp_listen的最后一個(gè)參數(shù)是允許的),因?yàn)樘捉涌诘刂方Y(jié)構(gòu)的長度在調(diào)用函數(shù)sendto()和recvfrom()時(shí)都是需要的,該函數(shù)的形式如下:#include"unp.h"intudp_client(constchar*hostname,constchar*service,void**saptr,

socklen_t*lenp);返回:若成功返回未連接套接口的描述字,若出錯(cuò)則不返回。#include"unp.h"

intudp_client(constchar*host,constchar*serv,void**saptr,socklen_t*lenp){intsockfd,n;structaddrinfo hints,*res,*ressave;bzero(&hints,sizeof(structaddrinfo));hints.ai_family=AF_UNSPEC;hints.ai_socktype=SOCK_DGRAM;if((n=getaddrinfo(host,serv,&hints,&res))!=0)err_quit("udp_clienterrorfor%s,%s:%s",host,serv,gai_strerror(n));ressave=res;do{sockfd=socket(res->ai_family,res->ai_socktype,res->ai_protocol);f(sockfd>=0)break; /*success*/}while((res=res->ai_next)!=NULL);if(res==NULL) /*errnosetfromfinalsocket()*/err_sys("udp_clienterrorfor%s,%s",host,serv);*saptr=Malloc(res->ai_addrlen);memcpy(*saptr,res->ai_addr,res->ai_addrlen);*lenp=res->ai_addrlen;freeaddrinfo(ressave);return(sockfd);}接下來看一下udp_connect()函數(shù),該函數(shù)創(chuàng)建一個(gè)已連接UDP套接口,該函數(shù)形式如下:#include"unp.h"intudp_connect(constchar*hostname,constchar*service);返回:如果成功則返回套接口描述字,若出錯(cuò)則不返回。當(dāng)?shù)玫揭堰B接UDP套接口后,在udp_client()函數(shù)中所需的后兩個(gè)參數(shù)就不再需要了。用戶可以用write函數(shù)代替sendto函數(shù),于是就不再需要返回套接口地址結(jié)構(gòu)和它的長度了。

intudp_connect(constchar*host,constchar*serv){intsockfd,n;structaddrinfohints,*res,*ressave;bzero(&hints,sizeof(structaddrinfo));hints.ai_family=AF_UNSPEC;hints.ai_socktype=SOCK_DGRAM;if((n=getaddrinfo(host,serv,&hints,&res))!=0)err_quit("udp_connecterrorfor%s,%s:%s",host,serv,gai_strerror(n));ressave=res;do{sockfd=socket(res->ai_family,res->ai_socktype,res->ai_protocol);if(sockfd<0)continue; /*ignorethisone*/if(connect(sockfd,res->ai_addr,res->ai_addrlen)==0)break; /*success*/Close(sockfd); /*ignorethisone*/}while((res=res->ai_next)!=NULL);if(r

溫馨提示

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

最新文檔

評論

0/150

提交評論