getaddrinfo() – Linux VS Windows

在Linux中,我可以使用调用getaddrinfo()到本地套接字getaddrinfo(NULL,port,&hints,&servinfo)来创build列表,如下所示:

  IPv4: 0.0.0.0 | socktype: 1 |protocol: 6 IPv4: 0.0.0.0 | socktype: 2 |protocol: 17 IPv4: 0.0.0.0 | socktype: 3 |protocol: 0 IPv6: :: | socktype: 1 |protocol: 6 IPv6: :: | socktype: 2 |protocol: 17 IPv6: :: | socktype: 3 |protocol: 0 

而在Windows中,任何与本地机器"NULL""localhost""127.0.0.1" (实际上不是URL)有关的调用似乎都失败了。

在Linux和Windows之间getaddrinfo()的用法有什么区别?

另外 – 我知道这样会使问题变成双重的 – 但是第一个程序的输出结果告诉了我什么? 那些内核能够为这个端口唯一的组合吗?

是的,这个问题是从比较着名的“Beej的networking编程指南”演变而来的。

导致这个问题的代码是这样的:

  struct addrinfo hints,*ai,*p; memset(&hints,0,sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE; int error; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6 hints.ai_socktype = SOCK_STREAM; if ((error = getaddrinfo("www.example.com", "http", &hints, &ai)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); exit(1); } else cout <<"Success with a URL\n"; if (error=(getaddrinfo("208.117.45.202",&port,&hints,&ai))){ cout<<"Cannot resolve any usable ports! : "<<gai_strerror(error)<< " : "<<error; if (ai == NULL) return -5; } 

谢谢!

有这些神奇的东西被称为手册页 。 例如, man 3 getaddrinfo清楚地说

如果在hints.ai_flags中指定了AI_PASSIVE标志,并且节点为NULL,那么返回的套接字地址将适合bind()一个将accept()连接的套接字。 返回的套接字地址将包含“通配符地址”(IPv4地址为INADDR_ANY,IPv6地址为IN6ADDR_ANY_INIT)。 通配符地址由应用程序(通常是服务器)使用,用于接受任何主机的网络地址上的连接。 如果节点不是NULL,那么AI_PASSIVE标志被忽略。

getaddrinfo()函数的用途很简单:它尽力将用户指定的字符串转换为数字数据,应用程序可以使用它来创建套接字,无论是监听传入连接还是连接到一个套接字。

getaddrinfo()是在POSIX.1-2001 (和RFC 2553 )中指定的,而且Microsoft从未遵循过可能会扩展或变态的标准,所以当然这在Windows中是完全不同的功能。 相关的MSDN页面表示它“提供了从ANSI主机名到地址的协议独立转换”。

你的程序的输出,因为node (第一个参数)是NULL ,并且在标志中有AI_PASSIVE ,你的程序可以(尝试)绑定到通配符地址列表,监听到你有port传入连接指定。

编码一致性发生了什么?

 memset(&hints,0,sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE; int error; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6 hints.ai_socktype = SOCK_STREAM; 

你首先使用sizeof(hints)hints ; 那么你设定了一些值; 然后用sizeof hints (不一致)再次将其归零; 那么你第二次设置了一些值,错过了其他值(特别是AI_PASSIVE标志)。 如果你一致的话,编程通常是最简单的。 避免(或多或少)同样的事情做两次也是明智的做法。 选择一个或另一个序列,但不要同时包含这两个序列。

这是否真的是你的问题的来源是一个单独的问题。 Nominal Animal的答案涵盖了很多相关的基础,尽管我没有验证微软的具体细节。