我想使用C#获取一个局域网中所有ip和mac地址的列表。目前我正在向局域网中的每个IP发送ARP数据包,例如192.168.0.1~192.168.0.254,以获取其mac地址,但是发送所有arp数据包并获得所有回复需要4分钟。 有没有其他方法可以做到这一点?非常感谢!
public void ScanLAN(IP startIP, IP endIP)
{
var targetIPList = new List<IPAddress>();
while (!startIP.Equals(endIP))
{
targetIPList.Add(startIP.IPAddress);
startIP.AddOne();
}
var arpPackets = new Packet[targetIPList.Count];
for (int i = 0; i < arpPackets.Length; ++i)
{
arpPackets[i] = BuildRequest(targetIPList[i], LocalMAC, LocalIP);
}
//create a "tcpdump" filter for allowing only arp replies to be read
String arpFilter = "arp and ether dst " + LocalMAC.ToString();
//open the device with 20ms timeout
_device.Open(DeviceMode.Promiscuous, 20);
//set the filter
_device.Filter = arpFilter;
scanThread = new System.Threading.Thread(() =>
{
for (int i = 0; i < arpPackets.Length; ++i)
{
var lastRequestTime = DateTime.FromBinary(0);
var requestInterval = new TimeSpan(0, 0, 1);
var timeoutDateTime = DateTime.Now + timeout;
while (DateTime.Now < timeoutDateTime)
{
if (requestInterval < (DateTime.Now - lastRequestTime))
{
// inject the packet to the wire
_device.SendPacket(arpPackets[i]);
lastRequestTime = DateTime.Now;
}
//read the next packet from the network
var reply = _device.GetNextPacket();
if (reply == null)
{
continue;
}
// parse the packet
var packet = PacketDotNet.Packet.ParsePacket(reply.LinkLayerType, reply.Data);
// is this an arp packet?
var arpPacket = PacketDotNet.ARPPacket.GetEncapsulated(packet);
if (arpPacket == null)
{
continue;
}
//if this is the reply we're looking for, stop
if (arpPacket.SenderProtocolAddress.Equals(targetIPList[i]))
{
if (ResolvedEvent != null)
{
ResolvedEvent(this, new ResolvedEventArgs()
{
IPAddress = arpPacket.SenderProtocolAddress,
PhysicalAddress = arpPacket.SenderHardwareAddress
});
}
break;
}
}
}
_device.Close();
Console.WriteLine("exit scan");
if (ScanStopedEvent != null)
{
ScanStopedEvent(this, new EventArgs());
}
});
scanThread.Start();
}