2

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

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

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

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

4

3 回答 3

1

因此,我决定包装 Windows API 将是最不混乱的解决方案,并提出以下内容供所有人查看:

首先,我创建了Friend NotInheritable Class一个名为NativeMethods的私有构造函数(大致相当于 C# 中的静态内部类)和一个名为IPHelper的子类(也是静态内部类) 。这是我放置从 pinvoke.net (源代码)无耻复制的 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()
于 2012-11-30T14:56:17.433 回答
0

有关的:

接受的答案使用 COM,但引用了一个非常有趣的链接,指向似乎创建了基于 C# 的数据包捕获库的开发人员,以及如何使用它获取 ARP 信息的示例。也许这对你有用?

请注意,我不知道“SharpPcap”是否包装了非托管代码。

没有可以直接处理 ARP AFAIK 的内置托管代码。

于 2012-11-29T22:01:38.460 回答
0

我创建了您要求的这样一个库:ArpLookup

实际上,您不能使用套接字对象来生成 ARP 数据包,因为原始套接字被禁用/仅管理员/等。在所有相关的现代操作系统中。因为我想编写跨平台代码,所以我将您的两个想法都实现为一个更适合的 Linux,一个是 Windows。在 Windows 上使用本机 API。在 Linux 上,/proc/net/arp读取包含系统 arp 表的文件。如果未找到请求的 IP,则会发送 ping 并再次进行查找。这适用于 Linux,包括。Android(给定相关的应用权限)但不是在 macOS 上。

于 2019-12-19T16:59:42.137 回答