5.1 getaddrinfo() --- 准备运行

原文:https://beej.us/guide/bgnet/html/#getaddrinfoprepare-to-launch

 

5. 调用/捕获系统函数

       这部分我们使用系统的函数来访问网络他们在Unix的头文件里,以及任何支持套接字APP的操作系统(BSD、Windows、Linux、Mac等等)。当你调用他们中间的函数时,内核会自动帮助完成所有工作。

       大多数就卡在这些系统函数里。在这儿,因为你可能发现没有可用的man!好,为了帮助顺利适应它,我按照你的程序调用系统函数的顺序来讲解他们。

       那么,你需要一些牛奶和饼干,再给你提供一些样例代码。其它的就是你的勇气、高昂的勇气!你会发现原来竟然是如此的快乐!

       (请注意,为了代码的简洁,没有包含错误检查。在调用getaddrinfo()函数成功时会返回一个有效的链表(linked list)。有些程序使用原始的地址(properly addressed ---也可译原型的地址)这也可以。)

5.1 getaddrinfo() --- 准备运行

       这个是真正的默默无闻的函数,虽然它有没多参数,但是实际用起来很简单。

它对于你建立一个地址结构起到了简化的作用。

A tiny bit of history: it used to be that you would use a function called gethostbyname() to do DNS lookups. Then you’d load that information by hand into a struct sockaddr_in, and use that in your calls.

       值得庆幸的是,这不再是必要的了。在这现代化的时代,你已经有了getaddrinfo()函数并为你封装好了不少东西,其中包括DNS和服务名称查找!

       让我们一起来看看!

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    
    int getaddrinfo(const char *node,     // e.g. "www.example.com" or IP
                    const char *service,  // e.g. "http" or port number
                    const struct addrinfo *hints,
                    struct addrinfo **res);

       在这个函数里有3个输入参数和1个作为返回值的指向链表的指针res。

       入参node是要连接的主机名或者IP地址。

       下一个入参service是端口号,比如“80”,或者其它特定的服务名称像“http”、“ftp”、“telnet”、“smtp”等等。

       最后,入参hints指向一个你已经填写好了的addrinfo结构。

       下面的示例是服务器在你的主机IP地址和端口号3490监听。

请注意,他们没有做任何实际的监听或者网络设置;

它只是在设置了结构hints并且做了调用。

int status;
struct addrinfo hints;
struct addrinfo *servinfo;  // will point to the results

memset(&hints, 0, sizeof(hints)); // make sure the struct is empty
hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
hints.ai_flags = AI_PASSIVE;     // fill in my IP for me

if ((status = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    exit(1);
}

// servinfo now points to a linked list of 1 or more struct addrinfos

// ... do everything until you don't need servinfo anymore ....

freeaddrinfo(servinfo); // free the linked-list

 

       请注意:因为ai_family设置为 AF_UNSPEC 以达到与版本(IPv4 or IPv6)无关。

你也能设置专为IPv4或者IPv6工作以及其它的地址族。

       此外你在这儿看到了AI_PASSIVE标志;他告诉getaddrinfo()复制本机地址给套接字结构。这很好,因为没有硬编码。

       译者注上边的情况通常使用在服务器端!

                    

下边说的就是客户端的情况。

       示例:连接到www.example.net的3049端口。

int status;
struct addrinfo hints;
struct addrinfo *servinfo;  // will point to the results

memset(&hints, 0, sizeof(hints)); // make sure the struct is empty
hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets

// get ready to connect
status = getaddrinfo("www.example.net", "3490", &hints, &servinfo);

// servinfo now points to a linked list of 1 or more struct addrinfos

// etc.

 

我一直在说servinfo是包含所有地址信息的链接列表。

让我们编写一个快速的演示程序来展示这些信息。

这个程序在命令行上打印出你指定主机的IP地址。

showip.c所需头文件列表:

#include<stdio.h>

#include<string.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<netdb.h>

#include<arpa/inet.h>

流程图

 

 

       正如您所看到的,代码调用的getaddrinfo()来填写由res指向的链表,然后我们可以遍历列表以及打印在命令行上。

译者注:测试IPv6失败!请读者自行查找国内可用的IPv6站点。

 

       现在我们已经在控制之下,我们将使用getaddrinfo()得到的结果,我们要传递给其他socket函数,

终于,建立我们的网络连接!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值