了解 C 中的 getaddrinfo 函数

6 c linux network-programming getaddrinfo

我是 C 和套接字编程的新手,只是一个关于getaddrinfo功能的问题。的函数原型getaddrinfo为:

int getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **result);
Run Code Online (Sandbox Code Playgroud)

返回getaddrinfo一个结果,该结果指向一个addrinfo结构的链表,每个addrinfo结构都指向一个对应host和service的socket地址结构。 在此输入图像描述

以下是我的问题:

Q1-为什么需要返回一个指向结构体链表的addrinfo结果?我的意思是,给定一个主机和服务,这些只是一个唯一的套接字地址,它怎么可能是多个有效的套接字地址,因此需要一个链表?

Q2-最后一个参数是struct addrinfo **result,为什么是指向指针的指针?为什么不是struct addrinfo *result,然后getaddrinfo在内部创建某物并让result( struct addrinfo *)指向它?有人说这是由于内部getaddrinfo调用malloc,但我也可以这样编码

int main() 
{
   char *ptr_main;
   test(ptr_main);
   free(ptr_main);
}

void test(char * ptr)
{ 
    ptr = malloc(10); 
}
Run Code Online (Sandbox Code Playgroud)

所以函数的参数是char *ptr,而不是char **ptr

Rob*_*oni 6

getaddrinfo()返回地址列表,因为主机名可以包含多个地址。例如,那些需要通过不同 IP 分配访问者的高流量网站。

自从getaddrinfo()

将 gethostbyname(3)和 getservbyname(3) 函数提供的功能组合到一个接口中,但与后一个函数不同的是,getaddrinfo() 是可重入的,允许程序消除 IPv4 与 IPv6 的依赖关系

它可能会触发 DNS 会话来解析主机名。对于上述高流量站点,相同的主机名将对应于实际地址列表。


你还问:

struct addrinfo **result,为什么是指向指针的指针?

在 C 中,当函数需要修改某个东西时,它会作为函数的参数传递。因此,例如,如果您需要修改一个整数,则可以传递int *. 当您想通过参数返回某些内容时,这种特殊类型的修改在 C 中非常常见;在前面的示例中,我们可以通过访问作为参数传递的指针来返回一个额外的整数。

但是如果一个函数想要分配一些东西怎么办?它将在内部产生 a type * var = malloc(),这意味着type将返回一个指向的指针。为了将其作为参数返回,我们需要传递一个type **参数。

逻辑清楚吗?给定 a type,如果您希望将其作为参数返回,则必须将其定义为指向 的指针type

总之,在我们的例子中,函数getaddrinfo需要修改一个类型为 的变量struct addrinfo *struct addrinfo **参数类型也是如此。

简单说一下这个参数的含义:

getaddrinfo() 函数分配并初始化一个 addrinfo 结构的链表,每个与节点和服务匹配的网络地址对应一个链表,并受到提示施加的任何限制,并返回指向 res 中链表开头的指针。链表中的项目由 ai_next 字段链接。

正如你所看到的,我们实际上在函数内部进行了分配。因此,最终需要释放该内存:

freeaddrinfo() 函数释放为动态分配的链表资源分配的内存。


为什么不只是一个type *参数?

您的代码示例导致未定义的行为,当我运行它时,它导致程序崩溃。

为什么?就是我上面写的,在C中参数是按值传递的。这意味着如果是一个func(int c)函数,以这种方式调用

int b = 1234;

funct(b);
Run Code Online (Sandbox Code Playgroud)

c函数内部使用的参数将是的副本b,并且对其进行的任何更改都不会在函数外部保留。

同样的情况也会发生func(char * ptr)(请注意巨大的间距,以强调类型char *和变量的情况ptr):任何对 on 的更改都ptr不会在函数之外生存。**您将能够更改它指向的内存,并且这些更改将在函数返回后可用,但作为参数传递的变量将与调用func().

ptr_main在您的示例中,在test调用之前的值是什么?我们不知道,因为该变量尚未初始化。因此,行为是未定义的。

如果您仍然有疑问,这里有一个程序演示了通过值获得的新分配的地址不能从外部访问the function

#include <stdlib.h>
#include <stdio.h>

void test(char * ptr)
{ 
    ptr = malloc(10); 

    printf("test:\t%p\n", ptr);
}

int main() 
{
    char *ptr_main = (char *) 0x7777;

    printf("main-1:\t%p\n", ptr_main);
    test(ptr_main);
    printf("main-2:\t%p\n", ptr_main);
}
Run Code Online (Sandbox Code Playgroud)

输出:

main-1: 0000000000007777
test:   0000000000A96D60
main-2: 0000000000007777
Run Code Online (Sandbox Code Playgroud)

即使在函数调用之后,它的值ptr_main在我初始化它之后也是相同的(0x7777)。