我正在尝试利用(vb).NET中ARP协议的强大功能来构建家庭LAN上所有联网设备及其硬件(MAC)地址的列表。我已经想出了如何计算子网上的所有IP地址,但我找不到发送ARP请求并阅读响应的简洁方法。
请注意,所有联网设备都包含非Windows设备(例如智能手机)。这意味着 WMI是不可能的。
现在我不知道哪种方式更麻烦:A)将本地IP helper API包装在托管代码中以便使用其SendArp方法,或者B)向每个主机发送ping请求以便填充ARP缓存,然后解析arp.exe -a
的输出。
有没有人知道使用托管代码处理ARP请求/响应的方法?使用套接字对象和一些魔法实现它似乎并不困难,但我找不到任何提供ARP API的第三方网络库。我恐怕我不够自己创造一个。
答案 0 :(得分:1)
所以我决定将Windows API包装起来是最不凌乱的解决方案,并为所有人提供以下内容:
首先,我创建了一个Friend NotInheritable Class
,其中包含名为 NativeMethods 的私有构造函数(大致相当于C#中的静态内部类),其子类(也是静态内部)名为 IPHelper 即可。这就是我放置了我从pinvoke.net(source)无耻复制的DllImport。
Friend NotInheritable Class NativeMethods
Private Sub New()
End Sub
Friend NotInheritable Class IPHelper
Private Sub New()
End Sub
' Possible return values
Friend Const NO_ERROR As Integer = 0
Friend Const ERROR_BAD_NET_NAME As Integer = 67
Friend Const ERROR_BUFFER_OVERFLOW As Integer = 111
Friend Const ERROR_GEN_FAILURE As Integer = 31
Friend Const ERROR_INVALID_PARAMETER As Integer = 87
Friend Const ERROR_INVALID_USER_BUFFER As Integer = 1784
Friend Const ERROR_NOT_FOUND As Integer = 1168
Friend Const ERROR_NOT_SUPPORTED As Integer = 50
' API function declaration.
<DllImport("iphlpapi.dll", SetLastError:=True)>
Friend Shared Function SendARP(
DestIP As UInt32,
SrcIP As UInt32,
pMacAddr() As Byte,
ByRef PhyAddrLen As Int32) As UInt32
End Function
End Class
End Class
现在最重要的是我编写了一个使用SendARP方法的公共类 ArpRequest 。
Imports System.Net
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Imports System.IO
Imports System.Net.NetworkInformation
Public Class ArpRequest
Private _address As IPAddress
Public Sub New(address As IPAddress)
_address = address
End Sub
''' <summary>
''' Gets the MAC address that belongs to the specified IP address.
''' </summary>
''' <remarks>This uses a native method and should be replaced when a managed alternative becomes available.</remarks>
Public Function GetResponse() As PhysicalAddress
Dim ip As UInteger = BitConverter.ToUInt32(_address.GetAddressBytes(), 0)
Dim mac() As Byte = New Byte(5) {}
Dim ReturnValue As Integer = CInt(NativeMethods.IPHelper.SendARP(CUInt(ip), 0, mac, mac.Length))
If ReturnValue = NativeMethods.IPHelper.NO_ERROR Then
Return New PhysicalAddress(mac)
Else
' TODO: handle various SendARP errors
' http://msdn.microsoft.com/en-us/library/windows/desktop/aa366358(v=vs.85).aspx
Throw New Win32Exception(CInt(ReturnValue))
End If
End Function
End Class
用法很简单(但请注意Win32Exceptions):
Dim ip = System.Net.IPAddress.Parse("0.0.0.0") ' replace with actual ip
Dim arp = New ArpRequest(ip)
Dim hardwareAddress = arp.GetResponse()
答案 1 :(得分:0)
相关:
接受的答案使用了COM,但引用了一个非常有趣的链接,这个链接似乎已经创建了一个基于C#的数据包捕获库,以及它如何用于获取ARP信息的示例。也许这对你有用吗?
请注意,我不知道“SharpPcap”是否包含非托管代码。
没有可以直接处理ARP AFAIK的内置托管代码。
答案 2 :(得分:0)
我创建了一个您要的图书馆:ArpLookup。
实际上,您不能使用套接字对象来生成ARP数据包,因为原始套接字已禁用/仅管理员/等。在所有相关的现代OS中。因为我想编写跨平台的代码,所以我将两种想法都实现为更好的Linux平台,一种Windows平台。在Windows上,使用本机API。在Linux上,将读取包含系统arp表的<html>
<head>
<script language="JavaScript">
<!-- hide this script from old browsers
function temp(form)
{
var f = parseFloat(form.DegF.value, 10);
var c = 0;
c = (f - 32.0) * 5.0 / 9.0;
form.DegC.value = c;
}
// done hiding from old browsers -->
</script>
</head>
<body>
<FORM>
<h2>Fahrenheit to Celsius Converter</h2>
Enter a temperature in degrees F:
<INPUT NAME="DegF" VALUE="0" MAXLENGTH="15" SIZE=15>
<p>
Click this button to calculate the temperature
in degrees C:
<INPUT NAME="calc" VALUE="Calculate" TYPE=BUTTON
onClick=temp(this.form)>
<p>
Temperature in degrees C is:
<INPUT NAME="DegC" READONLY SIZE=15>
</FORM>
</body>
</html>
文件。如果未找到要求的IP,则发送ping并再次执行查找。这适用于Linux incl。 Android(具有相关的应用权限),但不适用于macOS。