`
kenby
  • 浏览: 717003 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

gethostbyname和struct hostent详解

阅读更多

struct hostent *gethostbyname(const char *name);

gethostbyname函数根据域名解析出服务器的ip地址,它返回一个结构体struct hostent:


#include <netdb.h>

struct hostent {
	char  *h_name;            /* official name of host */
	char **h_aliases;         /* alias list */
	int    h_addrtype;        /* host address type */
	int    h_length;          /* length of address */
	char **h_addr_list;       /* list of addresses */
}
#define h_addr h_addr_list[0]  /* for backward compatibility */


除了服务器的ip地址外,这个结构体还包含了更多服务器的信息,有:


char *h_name

This is the “official” name of the host. 


char **h_aliases

These are alternative names for the host, represented as a null-terminated vector of strings. 

主机的可选名字,以NULL做为结束标记


int h_addrtype

This is the host address type; in practice, its value is always either AF_INET or AF_INET6, with the latter being used for IPv6 hosts. In principle other kinds of addresses could be represented in the database as well as Internet addresses; if this were done, you might find a value in this field other than AF_INET or AF_INET6. See Socket Addresses. 


int h_length

This is the length, in bytes, of each address. 

ip地址的长度,ipv4对应4个字节


char **h_addr_list

This is the vector of addresses for the host. (Recall that the host might be connected to multiple networks and have different addresses on each one.) The vector is terminated by a null pointer. 

一般主机可以有多个ip地址,比如www.163.com就有121.14.228.43和121.11.151.72两个ip,h_addr_list就用来

保存多个ip地址


char *h_addr

This is a synonym for h_addr_list[0]; in other words, it is the first host address.

即为h_addr_list[0],表示第一个地址,这个符号其实是兼容老系统而存在的



我们写一个程序来获取主机www.163.com的详细信息:


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define SERVPORT 80

int main(int argc, char **argv)
{
    int i, sockfd;
    struct hostent *host;
    struct sockaddr_in serv_addr;

    if ((host = gethostbyname(argv[1])) == NULL) {
        printf("gethostbyname error\n");
        exit(0);
    }

    printf("official name: %s\n\n", host->h_name);
    printf("address length: %d bytes\n\n", host->h_length);

    printf("host name alias: \n");
    for (i = 0; host->h_aliases[i]; i++) {
        printf("%s\n", host->h_aliases[i]);
    }
    printf("\naddress list: \n");

    for (i = 0; host->h_addr_list[i]; i++) {
        if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) == -1) {
            printf("socket error\n");
            exit(0);
        }
        // 先清零,然后用struct sockaddr_in来填值
        bzero(&serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(SERVPORT);
        /* h_addr_list[i]指向in_addr类型 */
        serv_addr.sin_addr = *((struct in_addr *)host->h_addr_list[i]);
        const char *ip = inet_ntoa(serv_addr.sin_addr);
        printf("connect to %s  ", ip);

        // 系统调用的时候,把sockaddr_in转换成sockaddr
        if (connect(sockfd, (struct sockaddr *)&serv_addr, \
                    sizeof(struct sockaddr)) == -1) {
            printf("error\n");
            exit(0);
        }
        printf("success\n");
    }

    return 0;
}


运行结果如下:


这个程序首先调用gethostbyname得到服务器的各种信息,其中就包含它拥有的ip地址,保存在h_addr_list中,然后

对于h_addr_list中的每个ip地址,都调用connect连接其80端口。h_addr_list保存的ip地址类型是char *,

struct sockaddr_in中sin_addr的类型是struct in_addr,而程序中却直接把h_addr_list[i]强制转换成struct in_addr *

serv_addr.sin_addr = *((struct in_addr *)host->h_addr_list[i]);

这是没有问题的,因为h_addr_list保存的并不是真正的字符串,而是指向struct in_addr类型的指针。



另外,struct in_addr用来表示ip地址,本质上是一个long类型,刚好4个字节。然后我们调用inet_ntoa把它转换

成可读性更强的dots-and-number字符串。关于ip地址和dots-and-number字符串之间的转换有4个函数:

 

#include <arpa/inet.h>
/* network to ascii */
char *inet_ntoa(struct in_addr in);     						
/* ascii to network */
int inet_aton(const char *cp, struct in_addr *inp);

const char *inet_ntop(int af, const void *src, 
								char *dst, socklen_t size);
int inet_pton(int af, const char *src, void *dst);  /* presentation format to network */
 

 

inet_ntoa和inet_aton不支持ipv6, 据说迟早要废除,不过目前来说,很多系统都可以看见这两个函数

分享到:
评论

相关推荐

    VC gethostbyname获取主机名和IP地址.rar

     struct hostent * phost;  phost = gethostbyname(szhostname);//根据主机名获得IP地址  m_strName=szhostname;  int h_length=4;  for( int j = 0; j {   CString addr;   if( j &gt; 0 )   str = ".";   ...

    域名测试程序

    测试域名:函数:int gethostname(char *name, size_t len); int getdomainname(char *name,size_t len); struct hostent *gethostbyaddr(const char *name);...struct hostent *gethostbyname(const char *name);

    测试任意ip

    ip测试:用到函数:int gethostname(char *name, size_t len); int getdomainname(char *name,size_t len); struct hostent *gethostbyaddr(const char *name);...struct hostent *gethostbyname(const char *name);

    用gethostbyname来获得域名信息

    用gethostbyname来获得域名信息

    快递信息 查询

    需要自行购买查询快递的API,不同的API地址不同,使用时需要修改修改.c中的 struct hostent *he = gethostbyname("cexpress.market.alicloudapi.com")中的地址和 Authorization:APPCODE 后面的内容

    php gethostbyname获取域名ip地址函数详解

    gethostbyname语法: string gethostbyname(string hostname); gethostbyname返回值: 字符串 函数种类: 网络系统 gethostbyname内容说明 本函数可返回某个机器名称 (Domain Name) 的 IP 网址 (IP Address)。若执行...

    gethostbyname 用法

    gethostbyname 的用法,查询域名的IP,很简单,免费下载

    winsock四个网络程序源代码

    本程序包含四个网络程序,分别为客户端程序(listen),服务端程序(server),数据包... struct hostent* 主机信息(结构体指针) 3.WSAIoctl(SIO_RCVALL) setsockopt(); ioctlsocket(s, SIO_RCVALL, &dwBufferInlen);

    linux网络编程学习笔记

    struct hostent *gethostbyname(const char *hostname) struct hostent *gethostbyaddr(const char *addr,int len,int type) 在;中有 struct hostent的定义 struct hostent{ char *h_name; /* 主机的正式名称 */...

    get_myaddress.rar_GetHostByName_gethostbyname linux

    use gethostbyname, which would invoke NIS.

    vc++telnet实例

    struct hostent *he; signal(SIGALRM, break_check); alarm(1); bzero((char*) &blah;, sizeof(blah)); blah.sin_family = AF_INET; blah.sin_port = htons(port); printf("\r\n连线中.... \r\n"); ...

    gethostbyname可执行代码

    有域名获得IP地址,不单单获得首选IP地址,能够将IP地址列表全部打印出来

    gethostbyname_r在某些linux版本中多线程不安全问题.pdf

    gethostbyname_r在某些linux版本中多线程不安全问题.pdf

    gethostbyname_crash

    TestDll.exe调用cache.dll中的导出函数cache,在Win7下工作正常,但是在XP下执行到gethostbyname就会崩溃,如果把cache.dll编译为EXE那么cache函数在Win7和XP下都能正常...

    使用GetHostByName获取IP

    在C++Builder开发环境下,使用GetHostByName获取域名或者网站的IP地址

    gethostbyname.c

    gethostbyname.c

    httpdownfile

    struct hostent *host; int portnumber,nbytes; char host_addr[256]; char host_file[1024]; char local_file[256]; FILE * fp; char request[1024]; int isend, totalsend; int i; char * pt;...

    gethostbynameAndgetservbyname.tar.gz

    gethostbynameAndgetservbyname.tar.gz 使用gethostbyname和getservbyname的获取时间程序。《unix网络编程》第11章程序。

    CVE-2015-0235-workaround:一个共享库包装器,对易受攻击的函数进行额外检查 gethostbyname2_r gethostbyname_r(GHOST 漏洞)

    CVE-2015-0235-解决方法又名 GHOST glibc 漏洞一个共享库包装器,对易受攻击的函数 gethostbyname2_r 和 gethostbyname_r 进行额外检查。 CVE-2015-0235 的正确解决方案是将 glibc 至少升级到 glibc-2.18。 在某些...

Global site tag (gtag.js) - Google Analytics