有什么方法可以改变同步Windows API SendARP的行为?

jfl*_*fly 10 c++ winapi multithreading asynchronous arp

我正在Windows上编写本地网络扫描程序,以查找具有IP帮助程序功能的在线主机,这相当于nmap -PR没有WinPcap.我知道如果远程主机没有响应,SendARP将阻塞并发送arp请求3次,所以我用std::aync它为每个主机创建一个线程,但问题是我想每20ms发送一个ARP请求所以它不会太多在很短的时间内很多arp数据包.

#include <iostream>
#include <future>
#include <vector>

#include <winsock2.h>
#include <iphlpapi.h>


#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

using namespace std;

int main(int argc, char **argv)
{
    ULONG MacAddr[2];       /* for 6-byte hardware addresses */
    ULONG PhysAddrLen = 6;  /* default to length of six bytes */
    memset(&MacAddr, 0xff, sizeof (MacAddr));
    PhysAddrLen = 6;

    IPAddr SrcIp = 0;
    IPAddr DestIp = 0;

    char buf[64] = {0};

    size_t start = time(NULL);

    std::vector<std::future<DWORD> > vResults;

    for (auto i = 1; i< 255; i++)
    {
        sprintf(buf, "192.168.1.%d", i);
        DestIp = inet_addr(buf);
        vResults.push_back(std::async(std::launch::async, std::ref(SendARP), DestIp, SrcIp, MacAddr, &PhysAddrLen));
        Sleep(20);
    }

    for (auto it= vResults.begin(); it != vResults.end(); ++it)
    {
        if (it->get() == NO_ERROR)
        {
            std::cout<<"host up\n";
        } 
    }

    std::cout<<"time elapsed "<<(time(NULL) - start)<<std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

起初我可以通过Sleep(20)在启动一个线程后调用来做到这一点,但是一旦SendARP在这些线程中重新发送ARP请求,如果没有来自远程主机的回复,它就不受我的控制,我在很短的时间内看到了很多请求(<10ms)在Wireshark中,我的问题是:

  1. 有什么办法让SendARP异步?
  2. 如果没有,我可以控制SendARP线程的发送时间吗?

A. *_*iak 0

似乎没有任何方法可以强制SendARP以非阻塞方式行事,似乎当主机无法访问时,它会在放弃之前尝试重新查询几次。

至于解决方案,没有什么是你想听的。MSDN 文档指出,有一个较新的 API 已弃用,SendARP称为ResolveIpNetEntry2,它也可以执行相同的操作,但它的行为方式似乎也相同。

它接收到的结构体包含一个名为ReachabilityTime.LastUnreachable节点在未收到可达性确认后假定邻居不可达的时间(以毫秒为单位)。

然而,它似乎并没有产生任何实际效果。

最好的方法是使用 WinPCap 或其他驱动程序,似乎没有办法解决用户空间中的问题。