并行ping多个网络设备的最佳方法是什么?

Dr.*_*eel 7 delphi network-programming ping polling iocp

我通过迭代ping在网络中调查了很多设备(超过300个).

程序按顺序轮询设备,因此速度很慢.我想提高民意调查的速度.

在Delphi 7中有一些方法可以做到这一点:

  1. 每个设备都有一个执行ping的线程.手动管理线程.
  2. 学习和使用Indy 10.需要举例.
  3. 根据窗口消息使用重叠I/O.
  4. 根据事件使用完成端口.

什么是更快,更容易?请举例说明一些示例或链接.

Llo*_*oyd 9

使用ICMP充斥网络并不是一个好主意.

您可能需要考虑某种线程池并对ping请求进行排队,并且有一定数量的线程在执行请求.

  • 啊,回忆.一位同事曾几乎用对话的方式询问过"我怎样才能同时发送几个ping?" 我的简短回答是"把它们放在线程中".半小时后,我们得到一个系统管理员冲进我们的办公室,尖叫着"黑客"我们的网络. (14认同)
  • 从最初的问题来看,很明显提问者已经进行了ping(当前连续),因此告诉他他不应该做他已经做过的事情(而且似乎需要这样做)并不是很有效率. (2认同)
  • @Thorsten - ping 不是问题。洪水是。使用许多线程 + ICMP 就足够绳索了……用脚射击自己! (2认同)

Tho*_*ler 6

我个人会选择IOCP.我在NexusDB中非常成功地使用它来进行传输实现.

如果要使用并行阻塞套接字和线程执行300个发送/接收周期,则最终需要300个线程.

使用IOCP,在将套接字与IOCP关联后,您可以执行300次发送操作,它们将在操作完成之前立即返回.操作完成后,所谓的完成包将排队到IOCP.然后,您有一个等待IOCP的线程池,操作系统会在完成数据包进入时唤醒它们.为了完成发送操作,您可以执行接收操作.接收操作也会立即返回,一旦实际完成,就会排队到IOCP.

关于IOCP的真正特殊之处在于它知道哪些线程属于它并且当前正在处理完成包.如果活动线程的总数(不在内核模式等待状态中)低于IOCP的并发数(默认情况下等于计算机上可用的逻辑核心数),则IOCP仅唤醒新线程.此外,如果有线程在IOCP上等待完成包(由于活动线程的数量等于并发数,尽管由于完成包排队而尚未启动),当前正在处理的其中一个线程一个完成包因任何原因进入内核模式等待状态,其中一个等待线程被启动.

返回IOCP的线程以LIFO顺序获取完成包.也就是说,如果一个线程正在返回IOCP并且仍然有等待的完成包,那么该线程直接获取下一个完成包,而不是进入等待状态,并且线程等待最长时间唤醒.

在最佳条件下,您将拥有多个线程,这些线程等于并发运行的可用核心数(每个核心上一个),获取下一个完成包,处理它,返回IOCP并直接获取下一个完成包,所有这些都没有进入内核模式等待状态或线程上下文切换必须发生.

如果您将拥有300个线程和阻塞操作,不仅会浪费至少300 MB的地址空间(对于堆栈的保留空间),而且当一个线程进入等待状态时,您还会有常量的线程上下文切换(等待)发送或接收完成)和完成发送或接收唤醒的下一个线程. - Thorsten Engler 12小时前


War*_* P 5

Windows上不推荐直接ICMP访问.可以直接访问Windows上的ICMP协议.由于恶意使用ICMP/ping/traceroute样式的原始套接字,我相信在某些版本的Windows上你需要使用Windows自带的api.特别是Windows XP,Vista和Windows 7不允许用户程序访问原始套接字.

我在ICMP.dll中使用了canned-functions,这是一些Delphi ping组件所做的,但下面的评论提醒我这被认为是"使用未记录的API接口".

这是主要的delphi ping组件调用本身的示例:

function TICMP.ping: pIcmpEchoReply;
{var  }
begin
  // Get/Set address to ping
  if ResolveAddress = True then begin
    // Send packet and block till timeout or response
    _NPkts := _IcmpSendEcho(_hICMP, _Address,
                            _pEchoRequestData, _EchoRequestSize,
                            @_IPOptions,
                            _pIPEchoReply, _EchoReplySize,
                           _TimeOut);
    if _NPkts = 0 then begin
      result := nil;
      status := CICMP_NO_RESPONSE;
    end else begin
      result := _pIPEchoReply;
    end;
  end else begin
    status := CICMP_RESOLVE_ERROR;
    result := nil;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

我相信大多数现代Ping组件实现将基于与上面相似的代码,并且我已经使用它在后台线程中运行此ping操作,没有任何probems.(演示程序包含在下面的链接中).

这里是基于ICMP.DLL演示的完整示例源代码.

更新在About.com上可以找到更现代的IPHLPAPI.DLL示例.