【发布时间】:2017-09-23 09:12:26
【问题描述】:
我正在 Windows 上编写一个本地网络扫描程序来查找具有 IP 助手功能的在线主机,这相当于 nmap -PR 但没有 WinPcap。我知道SendARP 会在远程主机没有响应的情况下阻塞并发送 3 次 arp 请求,所以我使用std::aync 为每个主机创建一个线程,但问题是我想每 20 毫秒发送一次 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;
}
起初我可以通过在启动线程后调用Sleep(20) 来做到这一点,但是一旦这些线程中的SendARP 重新发送 ARP 请求,如果没有来自远程主机的回复,它就超出了我的控制范围,我看到了很多请求在 Wireshark 中很短的时间内(
- 有什么方法可以使
SendARP异步? - 如果不行,可以在线程中控制
SendARP的发送时间吗?
【问题讨论】:
-
简单地限制未解决的 ARP 请求的数量似乎更实用。即首先发送 5 个请求,当您收到回复时,发送更多。
-
我想要一个本地网络的快速 ARP 扫描(在 5 秒内),对于典型的
/24网络,每 20 毫秒发送一次 ARP 请求扫描整个网络大约需要 5 秒,但SendARP可能如果远程主机在 Windows 7/8/10 上关闭,则阻止 3 秒。 -
我错过了这个问题。 “在很短的时间内有很多请求”表明速率太高,而“我想要快速扫描”表明速率太低。它是什么?您将需要 254 个线程,因为在 5 秒的时间间隔内不能有两个持续 3 秒的阻塞调用。所有 254 个呼叫必须在前两秒内启动。
-
鉴于您无法控制 SendArp 超时和重新传输的内部...使用原始套接字发送您自己的 arp 请求可能是唯一的选择...缺点是应用程序必须以管理员身份运行...
-
这正是我想做的——控制速率,每 20 毫秒发送一次请求。如果
SendARP只发送一个 ARP 请求,我可以启动一个线程然后休眠 20 毫秒,但它没有。
标签: c++ multithreading winapi asynchronous arp