理解C中的getaddrinfo函数
我不熟悉C和socket编程,只是关于理解C中的getaddrinfo函数,c,linux,network-programming,getaddrinfo,C,Linux,Network Programming,Getaddrinfo,我不熟悉C和socket编程,只是关于getaddrinfo函数的一个问题。getaddrinfo的功能原型是: int getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **result); 和getaddrinfo返回一个结果,该结果指向addrinfo结构的链接列表,每个结构都指向对应于主机和服务的套接字地址结构。 以下是我的问题: Q1为什么
getaddrinfo
函数的一个问题。getaddrinfo
的功能原型是:
int getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **result);
和getaddrinfo
返回一个结果,该结果指向addrinfo结构的链接列表,每个结构都指向对应于主机和服务的套接字地址结构。
以下是我的问题:
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);
}
因此,函数的参数是char*ptr
,而不是char**ptr
getaddrinfo()
返回地址列表,因为主机名可以包含多个地址。例如,考虑那些需要通过不同IP分配访问者的高流量站点
自
将gethostbyname(3)和getservbyname(3)函数提供的功能组合到一个接口中,但与后一个函数不同,getaddrinfo()是可重入的,允许程序消除IPv4与IPv6之间的依赖关系
它可能会触发DNS会话以解析主机名。对于上述高流量站点,相同的主机名将对应于实际地址列表
你还问:
struct addrinfo**result
,为什么它是指向指针的指针
在C语言中,当某个函数必须修改它时,指向它的指针作为函数的参数传递。例如,如果您需要修改一个整数,您可以传递int*
。当您希望通过参数返回某些内容时,这种特殊的修改在C中非常常见;在前面的示例中,我们可以通过访问作为参数传递的指针来返回一个额外的整数
但是如果一个函数想要分配一些东西呢?它将在内部产生一个type*var=malloc()
,这意味着将返回指向type
的指针。为了将其作为参数返回,我们需要传递一个type**
参数
逻辑清楚吗?给定类型
,如果要将其作为参数返回,则必须将其定义为指向类型
的指针
总之,在我们的例子中,函数getaddrinfo
需要修改类型为struct addrinfo*
的变量,因此struct addrinfo**
是参数类型
仅提及此参数的含义:
getaddrinfo()函数分配并初始化addrinfo结构的链表,每个与节点和服务匹配的网络地址对应一个链表,受提示施加的任何限制,并返回指向列表开头的指针(以res表示)。链表中的项由ai_next字段链接
正如您所看到的,我们实际上在函数中有一个分配。因此,最终需要释放此内存:
函数的作用是:释放为动态分配的链表资源分配的内存
为什么不只是一个
类型*
参数?
您的代码示例导致未定义的行为,当我运行它时,它导致程序崩溃
为什么?是我在上面写的,在C中,参数是通过值传递的。这意味着在func(int c)
函数的情况下,以这种方式调用
int b = 1234;
funct(b);
函数内部使用的参数c
将是b
的一个副本,对其进行的任何更改都不会在函数之外继续存在
在func(char*ptr)
的情况下也会发生同样的情况(请注意巨大的空格,以强调类型是char*
,变量是ptr
):对ptr
的任何更改都不会在函数之外继续存在**您可以更改它指向的内存,这些更改将在函数返回后可用,但作为参数传递的变量将与调用func()
之前相同
在您的示例中,test
调用之前,ptr\u main
的值是多少?我们不知道,因为变量未初始化。因此,行为是未定义的
如果您仍有疑问,这里是一个程序,它演示了无法从函数外部访问通过value获得的新分配地址:
#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);
}
即使在函数调用之后,ptr\u main
的值也与我初始化它后的值相同(0x7777
)
“这只是一个唯一的套接字地址”不正确。例如,主机名可能有许多不同的地址与之关联。“并让result(struct addrinfo*)指向它”如果您的函数想要更改某些内容,它需要接受指向该内容的指针作为参数<代码>结果是一个指针,所以它需要一个指向指针的指针。谢谢你的回答,所以对于问题2,我也可以像
int test(char*ptr){ptr=malloc(10);}
,所以参数不需要是schar**ptr
@amjad-Uhm。。。不,我可能不够清楚,我得重写一下。参数是按值传递的,因此ptr在函数外部不可用(您将无法释放它)。所以如果你需要返回一个指针,你需要一个双指针参数
main-1: 0000000000007777
test: 0000000000A96D60
main-2: 0000000000007777