分类: 网络与安全
2014-12-26 09:38:32
最近使用socket编程, 用到这个函数。 网上资料很多,只是有一点没有提到,特记录下。
函数原型:
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
void freeaddrinfo(struct addrinfo *res);
struct addrinfo
{ int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr; /* 我觉得这个成员是这个函数最大的便利。 */
char *ai_canonname;
struct addrinfo *ai_next;
};
参数: node 即 主机名称 ,可以是主机名称字符串,比如“hostname", 也可以是IP地址的字符串,比如“ 192.169.1.1”
service 服务 即端口号 可以是一个服务的名称,比如"http", 也可以是一个数字字符串 ,比如“80” .
hints 可以理解为约束条件,即 你创建的,要获得的addrinfo结构,有什么约束。 在hints中进行设置
res 很明显,这个就是我们最终获得的addrinfo结构。
这个函数产生原因。 以前版本里面需要套接字编程,要得到sockaddr 类型: 必须使用两种函数 getserverbyname (一类的函数) 和 gethostent (一类的函数), 然后构建 sockaddr_in 结构,在强制类型转换得到 sockaddr结构。 但是 getaddrinfo有了这个函数,这里过程就不用了,直接调用,就能得到 sockaddr 。 简化了编程过程。
注意点是: 这个函数,说起来,是get ,但是其实可以理解为creat 或者是理解为构建 。 因为你可以随意构建自己的地址结构addrinfo。
下面解释一下 hints 参数。 为什么要有这个参数 ?
看一个小程序:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void main()
{
struct addrinfo *ailist, *aip;
struct addrinfo hint;
struct sockaddr_in *sinp;
char *hostname = "luoyedeshan"; /* 这是我的用户名 */
char buf[INET_ADDRSTRLEN];
char *server = "3294"; /* 这是服务端口号 */
const char *addr;
int ilRc;
hint.ai_family = AF_UNSPEC; /* hint 的限定设置 */
hint.ai_socktype = 0; /* 这里可是设置 socket type . 比如 SOCK——DGRAM */
hint.ai_flags = AI_PASSIVE; /* flags 的标志很多 。常用的有AI_CANONNAME; */
hint.ai_protocol = 0; /* 设置协议 一般为0,默认 */
hint.ai_addrlen = 0; /* 下面不可以设置,为0,或者为NULL */
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
ilRc = getaddrinfo(hostname, server, &hint, &ailist);
if (ilRc < 0)
{
char str_error[100];
strcpy(str_error,gai_strerror(errno));
printf("str_error = %s", str_error);
return;
}
for (aip = ailist; aip != NULL; aip = aip->ai_next) /* 显示获取的信息 */
{
sinp = (struct sockaddr_in *)aip->ai_addr; /* 为什么是for 循环 ,先向下看 */
addr = inet_ntop(AF_INET, &sinp->sin_addr, buf, INET_ADDRSTRLEN);
printf(" addr = %s", addr?addr:"unknow ");
printf("port = %d ", ntohs(sinp->sin_port));
printf(" \n");
}
}
/* 执行结果如下 */
[luoyedeshan@luoyedeshan wqr]$ ./a.out
addr = 0.0.0.0 port = 3294
addr = 0.0.0.0 port = 3294
addr = 0.0.0.0 port = 3294
addr = 192.168.1.100 port = 3294
addr = 192.168.1.100 port = 3294
addr = 192.168.1.100 port = 3294
细心的你,也许发现,为什么重复了3次, 0.0.0.0 是本地地址,没话说, 192.168.1.100是局域网地址, 也没什么,为什么会得到3个重复的呢??
这就是 hint的作用,源代码里面我没甚至什么,hint都为空,所有有3个。 你在hint设置了,就可以屏蔽掉一些对你没用的addrinfo结构. 虽然有三个,他们的IP地址和端口号都一样,但是 这三个套接字类型不一样。 我试过 ,分别为 下面三种套接字类型 SOCK_DGRAM SOCK_SEQPACKET SOCK_STREAM .
把上面的 ai_socktype 改为 SOCK_STREAM 就只显示一个了。
关于这个函数的具体在套接字应用,在网上很多都有了,随便找一个试试,就可以了,这里就不给代码了。