域名解析——gethostbyname()函数及socket客户端域名解析

1. gethostbyname()函数说明

gethostbyname()——用域名或主机名获取IP地址

头文件:

#include <netdb.h>
#include <sys/socket.h>

函数原型:

struct hostent *gethostbyname(const char *name);

这个函数的传入值是域名或者主机名。返回值是一个hostent的结构体。如果函数调用失败,返回NULL。结构如下:

struct hostent
{
        char    *h_name;               
        char    **h_aliases;
        int     h_addrtype;
        int     h_length;
        char    **h_addr_list;
};
  • char *h_name
    表示的是主机的规范名。例如www.google.com的规范名其实是www.l.google.com。
  • char **h_aliases
    表示的是主机的别名.www.google.com就是google他自己的别名。有的时候,有的主机可能有好几个别名,这些,其实都是为了易于用户记忆而为自己的网站多取的名字。
  • int h_addrtype
    表示的是主机ip地址的类型,到底是ipv4(AF_INET),还是pv6(AF_INET6)
  • int h_length
    表示的是主机ip地址的长度
  • char **h_addr_list
    表示的是主机的ip地址,注意,这个是以网络字节序存储的。千万不要直接用printf带%s参数来打这个东西,会有问题的哇。所以到真正需要打印出这个IP的话,需要调用inet_ntop()。
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)

这个函数,是将类型为af的网络地址结构src,转换成主机字节序的字符串形式,存放在长度为cnt的字符串中。
如果成功,返回指向dst的一个指针。
如果失败,返回值是NULL。

#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>

int main(int argc, char **argv)
{
        char            *ptr, **pptr;
        char            IP[32];
        struct hostent  *hptr;
        ptr = argv[1];

        if((hptr = gethostbyname(ptr)) == NULL)
        {
                printf("gethostbyname error for host:%s\n", ptr);
                return 0;
        }

        printf("official hostname:%s\n",hptr->h_name);
        for(pptr = hptr->h_aliases; *pptr != NULL; pptr++)
                printf("alias:%s\n",*pptr);

        switch(hptr->h_addrtype)
        {
                case AF_INET:
                case AF_INET6:
                        pptr = hptr->h_addr_list;
                        for(; *pptr != NULL; pptr++)
                                printf("IP address:%s\n",inet_ntop(hptr->h_addrtype, *pptr, IP, sizeof(IP)));
                        break;
                default:
                        printf("unknown address type\n");
                        break;
        }

        return 0;
}

运行结果如下:
./a.out www.baidu.com

official hostname:www.a.shifen.com
alias:www.baidu.com
IP address:36.152.44.96
IP address:36.152.44.95

./a.out www.google.com

official hostname:www.google.com
IP address:142.251.43.4

参考链接:https://blog.csdn.net/leesphone/article/details/2138775

2. socket客户端域名解析

示例代码仅供参考:

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

#define MSG_STR "Hello, world! HELLO, UNIX!"

void print_usage(char *program)
{
        printf("%s usage: \n", program);
        printf("-i(--ipaddr): sepcify server IP address\n");
        printf("-p(--port): sepcify server port\n");
        printf("-d(--domain):sepcify server domain\n");
}

int main(int argc, char *argv[])
{
        int                     client_fd = -1;
        int                     rv = -1;
        int                     PORT = 0;
        int                     ch;
        char                    *IP = NULL;
        char                    **pIP = NULL;
        char                    buf[1024];
        char                    str[32];
        char                    *domain = NULL;
        struct  sockaddr_in     serv_addr;
        struct hostent          *host = NULL;  //定义hostent结构体
        struct option           opts[] = {
                {"ipaddr", required_argument, NULL, 'i'},
                {"port", required_argument, NULL, 'p'},
                {"domain", required_argument, NULL, 'd'},
                {NULL, 0, NULL, 0}
        };			//参数解析

        while((ch = getopt_long(argc, argv, "i:p:d:", opts, NULL)) != -1) 	  //参数解析
        {
                switch(ch)
                {
                        case 'i':
                                IP = optarg;
                                break;
                        case 'p':
                                PORT = atoi(optarg);
                                break;
                        case 'd':
                                domain = optarg;
                                break;
                        default:
                                printf("Unknown return val: %d\n", ch);
                }
        }
        if(!PORT | !(!IP ^ !domain))		//此处判断域名和IP地址二选一
        {
                print_usage(argv[0]);
                return -1;
        }

        if(!IP)
        {
                if((host = gethostbyname(domain)) == NULL)
                {
                        printf("gethostbyname error: %s\n", strerror(errno));
                        return -1;
                }
                switch(host->h_addrtype)
                {
                        case AF_INET:
                        case AF_INET6:
                         		pIP = host->h_addr_list;
                                for(; *pIP != NULL; pIP++)
                                        printf("IP address:%s\n", inet_ntop(host->h_addrtype, *pIP, str, sizeof(str)));
                                IP = str;
                                break;
                        default:
                                printf("unknown address type\n");
                                break;
                }
        }
        printf("IP: %s\n", IP);
        client_fd = socket(AF_INET, SOCK_STREAM, 0);
        if(client_fd < 0)
        {
                printf("create client socket failure:%s\n", strerror(errno));
                return -1;
        }
        printf("create client socket[fd:%d] scuess\n",client_fd);

        memset(&serv_addr, 0, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port   = htons(PORT);
        inet_aton(IP, &serv_addr.sin_addr);
        endhostent();   //释放结构体
        host = NULL;    //防止野指针
        if(connect(client_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
        {
                printf("connect server [%s:%d] failure:%s\n", IP, PORT, strerror(errno));
                return -1;
        }
        printf("connect server [%s:%d] scuess!\n", IP, PORT);

        if(write(client_fd, MSG_STR, strlen(MSG_STR)) < 0)
        {
                printf("write failure:%s\n",strerror(errno));
                goto cleanup;
        }

        memset(buf, 0, sizeof(buf));
        if((rv = read(client_fd, buf, sizeof(buf))) < 0)
        {
                printf("write failure:%s\n",strerror(errno));
                goto cleanup;
        }
        else if(rv == 0)
        {
                printf("client connect to server get disconnectd\n");
                goto cleanup;
        }
        printf("read %d bytes data from server and echo it back:%s\n",rv, buf);

cleanup:
        close(client_fd);
}
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值