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