【问题标题】:Socket hostname lookup timeout: how to implement it?套接字主机名查找超时:如何实现?
【发布时间】:2014-08-15 16:58:46
【问题描述】:

我编写使用套接字的可移植 Windows/Linux 应用程序。我使用gethostbyname 函数来执行DNS 查找。 但是,我看不到如何设置 gethostbyname 超时并保护我的应用程序在名称查找期间不被挂起。 当然,可以在另一个线程上运行gethostbyname,这就是我所做的。但是,它仅适用于琐碎的应用程序。 我的应用程序并行使用 1000-3000 个连接。在这种情况下,问题是:如何处理超时线程?我没有看到好的解决方案。我们可以“忘记”它们,但是,我们的程序线程数可能会在不良网络上增长到无穷大。我们可以终止它们,但这个想法看起来很糟糕。根据我的经验,在数千个线程终止后,Windows 可能会崩溃,我不知道 Linux 在这种情况下会如何表现。 此外,线程创建需要很多资源;创建 3000 个线程只是为了运行 gethostbyname 函数并退出并不是一个好主意。 因此,对于真正复杂的应用程序,单独的线程看起来不是一个好主意。当然,另一种选择是编写自己的 DNS 客户端,但是,它也不好看。 在 Windows 和 Linux 上是否有任何“官方”方式(或更好的可移植方式)来获取具有自定义超时的主机地址?

【问题讨论】:

  • IIRC,一些 Windows 和 Windows Server 版本通过重叠的 I/O 机制 (GetAddrInfoEx) 支持具有超时的异步查找。但这很难移植。您可以实现一个固定大小的线程池(64?)来运行阻塞查询和一个由另一个线程运行的“DNSrequest”对象的增量队列来实现您的超时。您可以使用 POSIX 信号量和少量其他同步对象来实现它。
  • 您可以使用一些第三方库来解决或编写自己的实现。
  • @Martin James GetAddrInfoEx 是套接字 2,它不可移植,更糟糕的是,与使用套接字 1.1 的静态库(如 libcurl、openssl)一起编译是有问题的。可能不存在便携式解决方案...
  • @GoodGuySoft - 我很确定您可以使用 POSIX 线程和信号量等来实现这样的系统。您应该在尝试自己动手之前检查一两个库。不过,我会说,为每个查询持续创建、终止和销毁线程是一个非常糟糕的设计,原因有很多,其中一些你已经欣赏了。

标签: c++ c sockets timeout gethostbyname


【解决方案1】:

最便携的解决方案确实是使用单独的线程进行名称解析。这也记录在MSDN

存在执行异步名称查找的不可移植解决方案。

Linux glibc 2.2.3+:getaddrinfo_a

Windows:WSAAsyncGetHostByName 仅限 IPv4 :(

那里有异步 DNS 库:例如,TADNS 看起来很简单。

【讨论】:

    【解决方案2】:

    首先:不要使用gethostbyname(),它已经过时了。请改用getaddrinfo()

    您想要的是异步名称解析。这是一个常见的要求,但不幸的是没有“标准”方式,如何做到这一点。以下是我为您找到最佳解决方案的提示:

    1. 不要实现 DNS 客户端。名称解析不仅仅是 DNS。想想 mDNS、主机文件等等。使用像 getaddrinfo() 这样的系统函数,为您抽象出不同的名称解析机制。

    2. 一些系统提供异步版本的解析函数,例如 glibc 提供 getaddrinfo_a()

    3. 有异步解析库,围绕同步系统解析器函数。我首先想到了libasyncns

    4. Boost.Asio 支持将解析器与线程池一起使用。见here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-08
      • 1970-01-01
      • 2011-02-04
      • 1970-01-01
      • 2012-06-21
      • 2010-09-14
      • 1970-01-01
      • 2020-12-22
      相关资源
      最近更新 更多