netdb.h中定义的函数

本文介绍了网络编程中的两个关键函数:getaddrinfo和gethostbyname。getaddrinfo是一个用于将主机名或IP地址转换为结构化的地址信息列表的函数,支持IPv4和IPv6,并且能处理名字到地址和服务到端口的转换。而gethostbyname则将域名转化为IP地址。文章通过示例展示了它们在UDP服务器和客户端程序中的应用,并强调了使用域名而非直接IP地址的重要性。
摘要由CSDN通过智能技术生成

getaddrinfo

getaddrinfo() converts human-readable text strings representing hostnames or IP addresses into a dynamically allocated linked list of struct addrinfo structures. The function prototype for this function is specified as follows:

#include<netdb.h>

int getaddrinfo(const char *restrict hostname,
				const char *restrict service,
				const struct addrinfo *restrict hints,
				struct addrinfo **restrict res);

函数介绍

IPv6中引入的新的API,它既可用于IPv4也可用于IPv6。这个函数能够处理名字到地址以及服务器到端口这两种转换,返回的是一个struct addrinfo的结构体(列表)指针而不是一个地址清单。这些struct addrinfo结构体可以由套接字函数直接使用。如此一来,getaddrinfo函数将协议相关性安全隐藏在这个库函数内部。应用程序只需要处理由getaddrinfo函数填写的套接字地址结构。

参数

  • hostname:可以是主机名(“www.baidu.com”)或者是数字化的地址字符串(IPv4的点分十进制“192.168.1.100”,IPv6的16进制字符串“2000::1.2345.6789.abcd”),当传递NULL时,取决于hints标志位,这个地址可能是0.0.0.0或者127.0.0.1
    如果ai_flags中设置了AI_NUMERICHOST标志位,那么该参数只能是数字化的地址字符串,不能是域名。
    hostname和service可以设置为NULL,但是同时只能有一个NULL
  • service:指代服务名,可以是十进制的端口号字符串(“8080”),也可以是已定义的服务名称,如“ftp”、“http”等,此时a typical implementation uses getservbyname() to query the file /etc/services to resolve the service to a port number。如果此参数设定为NULL,那么返回的socketaddr中的端口号不会被设置。
  • hints:该参数指向用户设定的struct addrinfo结构体,只能设定该结构体中ai_family、ai_socketype、ai_protocol、和ai_flags四个域,其他域必须设定为0或者NULL,通常是申请结构体变量后使用memset初始化再设定指定的四个域。
    该参数可以设置为NULL,等价于ai_socktype=0,ai_protocol=0,ai_family=AF_UNSPEC,ai_flags=0(在GNU Linux中ai_flag=AI_V4MAPPED | AI_ADDRCONFIG,可以看作是GNU的改进。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • res:is a pointer that points to a new addrinfo structure with the information requested after successful completion of the function.[2] The function returns 0 upon success and non-zero error value if it fails.[3]

使用示例

下列程序阐述了如何使用getaddrinfo),gai_strerror(),freeaddrinfo()以及getnameinfo(3)。the programs are an echo server and client for UDP datagrams

//Server program
#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<netdb.h>

#define BUF_SIZE 500

int main(int argc,char *argv[]){
	struct addrinfo hints;
	struct addrinfo *result,*rp;
	int sfd,s;
	struct sockaddr_storage peer_addr;
	socklen_t peer_addr_len;
	ssize_t nread;
	char buf[BUF_SIZE];

	if(argc!=2){
		fprintf(stderr,"Usage: %s port\n",argv[0]);
		exit(EXIT_FAILURE);
	}

	memset(&hints,0,sizeof(struct addrinfo));
	hints.ai_family=AF_UNSPEC;			//allow IPv4 or IPv6
	hints.ai_socktype=SOCK_DGRAM;		//datagram socket
	hints.ai_flags=AI_PASSIVE;			//for wildcard  IP address
	hints.ai_protocol=0;				//any protocol
	hints.ai_canonname=NULL;
	hints.ai_addr=NULL;
	hints.ai_next=NULL;

	s=getaddrinfo(NULL,argv[1],&hints,&result);
	if(s!=0){
		fprintf(stderr,"getaddrinfo: %s\n",get_strerror(s));
		exit(EXIT_FAILURE);
	}

	/* 
		getaddrinfo() returns a list of address structures. Try each address
		until we successfully bind(2). If socket(2) or bind(2) fails, we (close
		the socket) and try the next address.
	*/

	for(rp=result,rp!=NULL,rp=rp->ai_next){
		sfd=socket(rp->ai_family,rp->ai_socktype,rp->ai_protocol);
		if(sfd==-1)
			continue;
		if(bind(sfd,rp->ai_addr,rp->ai_addrlen)==0)
			break;	//success
		
		close(sfd);
	}

	if(rp==NULL){			//no address succeeded
		fprintf(stderr,"boule not bind\n");
		exit(EXIT_FAILURE);
	}
	
	freeaddrinfo(result);

	//read datagrams and echo them back to sender
	for(;;){
		peer_addr_len=sizeof(struct sockaddr_storage);
		nread=recvfrom(sfd,buf,BUF_SIZE,0,(struct sockaddr *)&peer_addr,&peer_addr_len);
		if(nread==-1)
			continue;
		char host[NI_MAXHOST],service[NI_MAXSERV];
		//待补充,位于man getaddrinfo中
	}
}

gethostbyname

客户端中直接使用IP地址会有很大的弊端,一旦IP地址变化(IP地址会经常变动),客户端软件就会出现错误。而使用域名会方便很多,注册后的域名只要每年续费就永远属于自己,更换IP地址时修改域名解析即可,不会影响软件的正常使用。

这个函数的作用就是将域名转化为IP地址,函数原型如下:

struct hostent *gethostbyname(const char *hostname);

hostname为主机名,也就是域名,使用该函数时,只要传递名字字符串,就会返回域名对应的IP地址。返回的地址信息会装入hostent结构体,该结构体定义如下:

struct hostent{
	char *h_name;		//official name
	char **h_aliases;	//alias list
	int h_addrtype;		//host address type
	int h_length;		//address length
	char **h_addr_list;	//address list
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值