gethostbyname() 及 getaddrinfo() 用法探究

主要是如何使用两个函数的返回结构。在gethostbyname函数中,返回hostent,linux参考手册介绍如下:

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 */
}

具体用法可以通过以下代码看到:

#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    char *ptr, **pptr;
    char str[INET_ADDRSTRLEN];
    struct hostent * hptr;

    while (--argc > 0)
    {
        ptr = *++argv;
        if ((hptr = gethostbyname(ptr)) == NULL)
        {
            fprintf(stderr, "gethostbyname error for host%s : %s",
                    ptr, hstrerror(h_errno));
            continue;
        }
        printf("official hostname %s\n", hptr->h_name);

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

        switch (hptr->h_addrtype)
        {
            case AF_INET:
                pptr = hptr->h_addr_list;
                for (; *pptr != NULL; ++pptr)
                    printf("\taddress: %s\n",
                            inet_ntop(hptr->h_addrtype, *pptr,
                                str, sizeof(str)));
                break;
            default:
                fprintf(stderr, "unknown address type");
                exit(EXIT_FAILURE);
                break;
        }
    }
    return 0;
}

执行./hostent www.baidu.com

效果如下:

getaddrinfo函数则更加复杂,但是提供了更好的接口。

这是只展示一个示例程序。

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

void printAddressInfo(const struct addrinfo*);

int main(int argc, char* argv[])
{
    int n;
    struct addrinfo* res, *ressave;
    struct addrinfo hint;
    char* serv;

    if (argc < 2)
    {
        fprintf(stderr, "Usage: "
                "./getaddrinfo <hostname> [<service name"
                " or port name>]\n");
        exit(EXIT_FAILURE);
    }
    if (argc == 2)
        serv = NULL;
    else
        serv = argv[2];
    bzero(&hint, sizeof(hint));
    hint.ai_family = AF_UNSPEC;

    if ((n = getaddrinfo(argv[1], serv, &hint, &res)) != 0)
    {
        if (argc > 2)
            fprintf(stderr, "Cannot get information for "
                    "%s : %s\n\terror:%s\n",
                    argv[1], serv, gai_strerror(n));
        else
            fprintf(stderr, "Cannot get information for "
                    "%s\n\terror:%s\n",
                    argv[1], gai_strerror(n));
        exit(EXIT_FAILURE);
    }
    ressave = res;

    while (res != NULL)
    {
        printAddressInfo(res);
        res = res->ai_next;
    }

    freeaddrinfo(ressave);
    exit(EXIT_SUCCESS);
}

void printAddressInfo(const struct addrinfo* addr)
{
    char str[INET6_ADDRSTRLEN];
    short port;

    printf("ai_family: ");
    switch (addr->ai_family)
    {
        case AF_INET: {
            struct sockaddr_in* in;

            printf("ipv4\n");
            in = (struct sockaddr_in *)(addr->ai_addr);
            port = ntohs(in->sin_port);
            inet_ntop(AF_INET, &in->sin_addr, str, sizeof(str));
            break;
        }
        case AF_INET6: {
            struct sockaddr_in6* in6;

            in6 = (struct sockaddr_in6 *)(addr->ai_addr);
            port = ntohs(in6->sin6_port);
            inet_ntop(AF_INET6, &in6->sin6_addr, str, sizeof(str));
            printf("ipv6\n");
            break;
        }
        default:
            printf("Unknown\n");
            break;
    }
    printf("ai_socktype: ");
    switch (addr->ai_socktype)
    {
        case SOCK_STREAM:
            printf("stream\n");
            break;
        case SOCK_DGRAM:
            printf("dgram\n");
            break;
        case SOCK_SEQPACKET:
            printf("seqpacket\n");
            break;
        case SOCK_RAW:
            printf("raw\n");
            break;
        default:
            printf("others\n");
            break;
    }
    printf("protocol: ");
    switch (addr->ai_protocol)
    {
        case IPPROTO_TCP:
            printf("tcp\n");
            break;
        case IPPROTO_UDP:
            printf("udp\n");
            break;
        case IPPROTO_SCTP:
            printf("sctp\n");
            break;
        default:
            printf("others\n");
            break;
    }
    printf("address: %s\n", str);
    printf("port: %d\n", port);
    printf("canonical name: %s\n\n", addr->ai_canonname);
}

上述程序在输入:./getaddrinfo www.baidu.com http后,效果如下:

重点在于地址的显示。结构的内容。

时间: 2024-08-09 12:35:38

gethostbyname() 及 getaddrinfo() 用法探究的相关文章

Java中toArray的用法探究(java数组与list转换)

一.             Incident import Java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("1"); list.add("2"); String[] tt

浅谈getaddrinfo函数的超时处理机制

在sockproxy上发现,getaddrinfo 解析域名相比ping对域名的解析,慢很多.我觉得ping用了gethostbyname解析域名.问题变为getaddrinfo解析域名,是否比 gethostbyname慢.写测试程序,分别用getaddrinfo和gethostbyname解析,发现getaddrinfo确实慢. strace跟踪发现,getaddrinfo和DNS服务器通信10次,gethostbyname和DNS服务器通信2次. gethostbyname是古老的域名解析

VS2015搭建live555源码调试环境

静态库模块:BasicUsageEnvironment groupsock liveMedia UsageEnvironment rtsp服务器主程序:mediaServer VS添加头文件,和源码文件 静态库: 常规/配置类型:静态库.lib C/C++/常规/附加包含目录 将四个模块的include目录添加 库管理器/输出文件 指定输出文件 C/C++/代码生成/运行库:多线程调试MTd 出错处理 1)'fopen': This function or variable may be uns

游戏引擎网络开发者的 64 做与不做 | Part 1 | 客户端方面

摘要:纵观过去 10 年的游戏领域,单机向网络发展已成为一个非常大的趋势.然而,为游戏添加网络支持的过程中往往存在着大量挑战,这里将为大家揭示游戏引擎网络开发者的 64 个做与不做. [编者按]时下,游戏网络化已势不可逆,因此,对于游戏开发者来说,掌握网络引擎的打造技巧同样不可避免.近日,Research Industrial Systems Engineering GmbH 安全研究员 Sergey Ignatchenko「拥有 20 年以上的工程经验」在 IT Hare 上撰文,深入分享了游

VS2013使用rtklib中需要注意的一些问题(编译)

最近因为项目需要需要对rtcm数据进行解码,rtklib提供了很多底层的函数,准备直接输出标准DLL的方式供C#调用.下面把项目中引用rtklib源码需要注意的地方记录下. 1. 首先在vs2013中新建一个win32的dll项目 2. 在项目上添加一个文件夹[rtklibsrc]然后在文件夹上[添加现有项目]把rtklib的源文件加入工程.在rtklibsrc下建立rcv把rcv下面的文件也添加到工程 3. 现在开始编译工程,你会发现很多错误.下面我们一步步来解决错误. 1>  Q: erro

Windows7上用VS编译本地使用的live555

本文链接:https://www.jianshu.com/p/6ea100865744 环境 系统:Windows7 SP1 64位 编辑器:Visual Studio Community 2017 Live555:2018-01-24 准备工作 下载源码 http://www.live555.com/liveMedia/public/ 下载live555-latest.tar.gz,我的是2018-01-24版本 下载VS https://www.visualstudio.com/zh-han

99% 的人都不知道的 Kubernetes 网络疑难杂症排查方法

原文链接:Kubernetes 网络疑难杂症排查分享 大家好,我是 roc,来自腾讯云容器服务 (TKE) 团队,经常帮助用户解决各种 K8S 的疑难杂症,积累了比较丰富的经验,本文分享几个比较复杂的网络方面的问题排查和解决思路,深入分析并展开相关知识,信息量巨大,相关经验不足的同学可能需要细细品味才能消化,我建议收藏本文反复研读,当完全看懂后我相信你的功底会更加扎实,解决问题的能力会大大提升. 本文发现的问题是在使用 TKE 时遇到的,不同厂商的网络环境可能不一样,文中会对不同的问题的网络环境

docker之入门——安装及基本命令

Docker简介 Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目.它基于 Google 公司推出的 Go 语言实现. 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护. Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案. Docker 的基础是 Linux 容器(LXC)等技术. (背景),云计算兴起后,服务器硬件扩展非常便利,软件服务部署成为了瓶颈,docker趁势而

LINUX - 获取本地ip

Linux编程获取本机IP地址的几种方法 参考:https://blog.csdn.net/zhongmushu/article/details/89944990 在进行Linux网络编程时,经常会需要获取本机IP地址,除了常规的读取配置文件外,本文罗列几种个人所知的编程常用方法,仅供参考,如有错误请指出. 方法一:使用ioctl()获取本地IP地址 Linux下可以使用ioctl()函数以及结构体 struct ifreq和结构体struct ifconf来获取网络接口的各种信息.具体过程是先