Dr.*_*eel 7 delphi network-programming ping polling iocp
我通过迭代ping在网络中调查了很多设备(超过300个).
程序按顺序轮询设备,因此速度很慢.我想提高民意调查的速度.
在Delphi 7中有一些方法可以做到这一点:
什么是更快,更容易?请举例说明一些示例或链接.
使用ICMP充斥网络并不是一个好主意.
您可能需要考虑某种线程池并对ping请求进行排队,并且有一定数量的线程在执行请求.
我个人会选择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示例.