在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的答案涵盖了很多相关的基础,尽管我没有验证微软的具体细节。