【问题标题】:getaddrinfo() - Linux VS Windowsgetaddrinfo() - Linux VS Windows
【发布时间】:2013-07-03 14:33:45
【问题描述】:

在 Linux 中,我可以在本地套接字 getaddrinfo(NULL,port,&hints,&servinfo) 上使用对 getaddrinfo() 的调用来创建如下列表:

   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)相关的调用似乎都失败了。

getaddrinfo() 在 linux 和 windows 之间的使用有什么区别?

另外 - 我知道这种问题会使问题变得复杂 - 但是第一个程序的输出到底告诉我什么?这些是内核可以支持该端口的唯一组合吗?

是的,这个问题是从相当著名的“Beej's Guide to network programming”演变而来的。

导致此的代码如下:

      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;
}

谢谢!

【问题讨论】:

  • 您可能应该显示更多代码。 MSDN docs for getaddrinfo() 非常详尽,听起来确实应该可以工作,即使对于 localhost 也是如此。
  • 你确定你在windows平台上运行服务器(例如XAMPP)?
  • 不,没有服务器。我想知道作为服务器的状态是否会对getaddrinfo() 调用的行为产生影响……但其他问题让我倾向于考虑操作系统拆分……
  • 尝试安装 XAMPP,然后运行 ​​localhost 服务器,并尝试运行您的代码,并告诉我们它是否有效 :)
  • 我确实做到了.. 但我从来没有特别关注过这些,我会的,谢谢。我想我希望首先对底层套接字系统有一个基本的理解......这些库不会增加太多开销,是吗? ....如果您还记得一部非常著名的美国电影中的某句台词:i.imgur.com/FlzYTja.jpg

标签: c linux windows network-programming


【解决方案1】:

这些神奇的东西叫做man pages。例如,man 3 getaddrinfo 明确表示

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

getaddrinfo() 函数的目的很简单:它尽最大努力将用户指定的字符串转换为应用程序可用于创建套接字的数字数据,一个用于侦听传入连接或一个用于连接。

getaddrinfo() 是在POSIX.1-2001(和RFC 2553)中指定的,而众所周知,微软从不遵循它可以扩展或破坏的标准,所以当然它在 Windows 中是一个完全不同的功能。相关的MSDN page 说它“提供了从 ANSI 主机名到地址的独立于协议的转换。”

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

【讨论】:

    【解决方案2】:

    编码一致性发生了什么变化?

    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;
    

    你第一个零hintssizeof(hints);然后你设置一些值;然后用sizeof hints 再次将其归零(不一致);然后您第二次设置一些值并错过其他值(特别是AI_PASSIVE 标志)。如果你保持一致,编程通常是最简单的。避免(或多或少)重复做同样的事情也是明智的。选择一个或另一个序列,但不要同时包含两者。

    这是否真的是您的问题的根源是一个单独的问题。 Nominal Animalanswer 涵盖了许多相关领域,尽管我尚未验证 Microsoft 特定的详细信息。

    【讨论】:

    • 我让它上网了吗? 脸红是的,当然谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-06
    相关资源
    最近更新 更多