托管代码中的ARP请求

时间:2012-11-29 21:52:07

标签: .net vb.net networking arp

我正在尝试利用(vb).NET中ARP协议的强大功能来构建家庭LAN上所有联网设备及其硬件(MAC)地址的列表。我已经想出了如何计算子网上的所有IP地址,但我找不到发送ARP请求并阅读响应的简洁方法。

请注意,所有联网设备都包含非Windows设备(例如智能手机)。这意味着 WMI是不可能的

现在我不知道哪种方式更麻烦:A)将本地IP helper API包装在托管代码中以便使用其SendArp方法,或者B)向每个主机发送ping请求以便填充ARP缓存,然后解析arp.exe -a的输出。

有没有人知道使用托管代码处理ARP请求/响应的方法?使用套接字对象和一些魔法实现它似乎并不困难,但我找不到任何提供ARP API的第三方网络库。我恐怕我不够自己创造一个。

3 个答案:

答案 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。