vb.net 托管代码中的 ARP 请求
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13635414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ARP requests in managed code
提问by Steven Liekens
I'm trying to leverage the power of the ARP protocol in (vb) .NET to build a list of all networked devices on my home LAN as well as their hardware (MAC) address. I already figured out how to calculate all IP addresses on a subnet but I'm stuck finding a clean way to send an ARP request and read the response.
我正在尝试利用 (vb) .NET 中 ARP 协议的强大功能来构建家庭 LAN 上所有联网设备及其硬件 (MAC) 地址的列表。我已经想出了如何计算子网上的所有 IP 地址,但我一直在寻找一种干净的方法来发送 ARP 请求并读取响应。
Note that allnetworked devices includes non-windows devices (such as smartphones). This means WMI is out of the question.
请注意,所有联网设备都包括非 Windows 设备(例如智能手机)。这意味着WMI 是不可能的。
Now I don't know which way is more cumbersome: A) wrapping the native IP helperAPI in managed code in order to use its SendArp method, or B) sending a ping request to each host in order to fill the ARP cache and then parsing the output from arp.exe -a.
现在我不知道哪种方式更麻烦:A) 将本机IP 助手API包装在托管代码中以使用其 SendArp 方法,或 B) 向每个主机发送 ping 请求以填充 ARP 缓存,然后解析来自arp.exe -a.
Does anyone know a way to handle ARP requests/responses using only managed code? It doesn't seem very difficult to implement using socket objects and a little sprinkle of magic, but I couldn't find any third-party networking libraries that offer an ARP API. I'm afraid I'm not knowledgeable enough to create one myself.
有没有人知道只使用托管代码处理 ARP 请求/响应的方法?使用套接字对象和一点点魔法来实现似乎并不难,但我找不到任何提供 ARP API 的第三方网络库。恐怕我的知识不够,无法自己创建一个。
回答by Steven Liekens
So I've decided that wrapping the windows API would be the least messy solution and came up with the following for all to see:
所以我决定包装 windows API 将是最不混乱的解决方案,并提出以下内容供所有人查看:
First I created a Friend NotInheritable Classwith a private constructor named NativeMethods(roughly the equivalent of a static internal class in C#) with a subclass (also static internal) named IPHelper. This is where I put the DllImport which I shamelessly copied from pinvoke.net (source).
首先,我创建了一个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
Now on top of that I wrote a public class ArpRequestwhich consumes the SendARP method.
现在最重要的是,我编写了一个使用 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
Usage is simple (but watch out for Win32Exceptions):
用法很简单(但要注意 Win32Exceptions):
Dim ip = System.Net.IPAddress.Parse("0.0.0.0") ' replace with actual ip
Dim arp = New ArpRequest(ip)
Dim hardwareAddress = arp.GetResponse()
回答by Georg Jung
I created such a library you were asking for: ArpLookup.
我创建了您要求的这样一个库:ArpLookup。
Actually you can't use a socket object to produce ARP packets as raw sockets are disabled/admin-only/etc. in all relevant modern OSes. Because I wanted to write cross-platform code I implemented both of your ideas as one fit's Linux better, one Windows. On Windows the native API is used. On Linux the /proc/net/arpfile containing the system's arp table is read. If the asked-for IP is not found, a ping is sent and the lookup is done again. This works on Linux incl. Android (given relevant app permissions) but not on macOS.
实际上,您不能使用套接字对象来生成 ARP 数据包,因为原始套接字已禁用/仅限管理员/等。在所有相关的现代操作系统中。因为我想编写跨平台代码,所以我将您的两个想法实现为一个更好的 Linux,一个 Windows。在 Windows 上使用本机 API。在 Linux 上,/proc/net/arp读取包含系统 arp 表的文件。如果未找到请求的 IP,则会发送 ping 并再次进行查找。这适用于 Linux,包括。Android(已授予相关应用程序权限)但不适用于 macOS。
回答by pseudocoder
Related:
有关的:
The accepted answer uses COM, but cited there is also a quite interesting link to a developer who appears to have created a C#-based packet capture library, and example of how it can be used to get ARP information. Maybe that will work for you?
接受的答案使用 COM,但引用了一个非常有趣的链接,该链接指向似乎创建了基于 C# 的数据包捕获库的开发人员,以及如何使用它获取 ARP 信息的示例。也许这对你有用?
Note that I do not know if "SharpPcap" wraps unmanaged code.
请注意,我不知道“SharpPcap”是否包装了非托管代码。
There is no built-in managed code that can deal directly with ARP AFAIK.
没有可以直接处理 ARP AFAIK 的内置托管代码。

