这两个函数的头文件为#include<netdb.h>
gethostbyname函数原型为:struct hostent * gethostbyname(const char *name);
函数作用为:通过主机名来获取主机完整信息,参数指定目标主机的主机名。
返回的结构体类型定义如下:
struct hostent
{
char* h_name; /* 主机名 */
char** h_aliases; /* 主机别名列表,可能有多个 */
int h_addrtype; /* 地址类型(地址族) */
int h_length; /* 地址长度 */
char** h_addr_list; /* 按网络字节序列出的主机 IP 地址列表 */
};
gethostbyname函数通常先在本地的/etc/hosts配置文件中查找主机,如果没找到,再去访问DNS服务器。
getservbyname函数原型为:struct servent *getservbyname(const char *name, const char *proto);
name参数指定目标服务的名字,proto参数指定服务类型,可传TCP,UDP和NULL,传NULL表示获取所有服务类型。
函数作用为:根据名称获取某个服务的完整信息。
返回值类型定义如下:
struct servent {
char *s_name; /* official service name */
char **s_aliases; /* alias list */
int s_port; /* port number */
char *s_proto; /* protocol to use */
}
下面通过主机名和服务名来访问本地服务器上的daytime服务,获取本地机器的系统时间,来示范两个函数的应用,代码如下:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netdb.h>
#include<stdlib.h>
#include<assert.h>
#include<unistd.h>
#include<arpa/inet.h>
int main(int argc,char *argv[])
{
if(argc < 2)
{
printf("usage: %s service\n",argv[0]);
exit(1);
}
//获取主机信息
struct hostent *hostinfo = gethostbyname(argv[1]);
assert(hostinfo);
char ip[20];
printf("host ip is %s\n",inet_ntop(AF_INET,hostinfo->h_addr_list[0],ip,sizeof(ip)));
//获取服务信息
struct servent *servinfo = getservbyname("daytime","tcp");
assert(servinfo);
printf("daytime port is %d\n",ntohs(servinfo->s_port));
int sockfd = socket(AF_INET,SOCK_STREAM,0);
assert(sockfd > 0);
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = servinfo->s_port;
servaddr.sin_addr = *(struct in_addr*)hostinfo->h_addr_list[0];
int ret = connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
if(ret < 0)
{
perror("connect error");
exit(1);
}
char buf[BUFSIZ];
int n = read(sockfd,buf,sizeof(buf));
if(n > 0)
{
buf[n] = '\0';
printf("%s\n",buf);
close(sockfd);
}
else if(n == 0)
{
printf("Peer closed\n");
close(sockfd);
}
else{
perror("read error");
close(sockfd);
exit(1);
}
return 0;
}