我正在尝试编写一个函数,它以单个IP地址
作为参数,并查询本地网络上的机器获取其MAC地址
。
我看过许多例子,这些例子获取本地机器自己的MAC地址
,但是没有发现(我找到的)可以查询本地网络机器的例子。
我知道这样的任务是可行的,因为这个Wake on LAN scanner软件扫描本地IP范围并返回所有打开机器的MAC地址/主机名。
有人能告诉我如何开始尝试使用C#编写此函数吗?任何帮助将不胜感激。谢谢
编辑:
根据Marco Mp下面的评论,已经使用ARP表。 arp类
我正在尝试编写一个函数,它以单个IP地址
作为参数,并查询本地网络上的机器获取其MAC地址
。
我看过许多例子,这些例子获取本地机器自己的MAC地址
,但是没有发现(我找到的)可以查询本地网络机器的例子。
我知道这样的任务是可行的,因为这个Wake on LAN scanner软件扫描本地IP范围并返回所有打开机器的MAC地址/主机名。
有人能告诉我如何开始尝试使用C#编写此函数吗?任何帮助将不胜感激。谢谢
编辑:
根据Marco Mp下面的评论,已经使用ARP表。 arp类
public string GetMacAddress(string ipAddress)
{
string macAddress = string.Empty;
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
pProcess.StartInfo.FileName = "arp";
pProcess.StartInfo.Arguments = "-a " + ipAddress;
pProcess.StartInfo.UseShellExecute = false;
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.StartInfo.CreateNoWindow = true;
pProcess.Start();
string strOutput = pProcess.StandardOutput.ReadToEnd();
string[] substrings = strOutput.Split('-');
if (substrings.Length >= 8)
{
macAddress = substrings[3].Substring(Math.Max(0, substrings[3].Length - 2))
+ "-" + substrings[4] + "-" + substrings[5] + "-" + substrings[6]
+ "-" + substrings[7] + "-"
+ substrings[8].Substring(0, 2);
return macAddress;
}
else
{
return "not found";
}
}
非常晚的编辑: 在开源项目 iSpy (https://github.com/ispysoftware/iSpy) 中,他们使用了这段代码,看起来更好一些。
public static void RefreshARP()
{
_arpList = new Dictionary<string, string>();
_arpList.Clear();
try
{
var arpStream = ExecuteCommandLine("arp", "-a");
// Consume first three lines
for (int i = 0; i < 3; i++)
{
arpStream.ReadLine();
}
// Read entries
while (!arpStream.EndOfStream)
{
var line = arpStream.ReadLine();
if (line != null)
{
line = line.Trim();
while (line.Contains(" "))
{
line = line.Replace(" ", " ");
}
var parts = line.Trim().Split(' ');
if (parts.Length == 3)
{
string ip = parts[0];
string mac = parts[1];
if (!_arpList.ContainsKey(ip))
_arpList.Add(ip, mac);
}
}
}
}
catch (Exception ex)
{
Logger.LogExceptionToFile(ex, "ARP Table");
}
if (_arpList.Count > 0)
{
foreach (var nd in List)
{
string mac;
ARPList.TryGetValue(nd.IPAddress.ToString(), out mac);
nd.MAC = mac;
}
}
}
https://github.com/ispysoftware/iSpy/blob/master/Server/NetworkDeviceList.cs
更新2,虽然更晚了,但我认为它是最好的,因为它使用正则表达式来更好地检查精确匹配。
public string getMacByIp(string ip)
{
var macIpPairs = GetAllMacAddressesAndIppairs();
int index = macIpPairs.FindIndex(x => x.IpAddress == ip);
if (index >= 0)
{
return macIpPairs[index].MacAddress.ToUpper();
}
else
{
return null;
}
}
public List<MacIpPair> GetAllMacAddressesAndIppairs()
{
List<MacIpPair> mip = new List<MacIpPair>();
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
pProcess.StartInfo.FileName = "arp";
pProcess.StartInfo.Arguments = "-a ";
pProcess.StartInfo.UseShellExecute = false;
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.StartInfo.CreateNoWindow = true;
pProcess.Start();
string cmdOutput = pProcess.StandardOutput.ReadToEnd();
string pattern = @"(?<ip>([0-9]{1,3}\.?){4})\s*(?<mac>([a-f0-9]{2}-?){6})";
foreach (Match m in Regex.Matches(cmdOutput, pattern, RegexOptions.IgnoreCase))
{
mip.Add(new MacIpPair()
{
MacAddress = m.Groups["mac"].Value,
IpAddress = m.Groups["ip"].Value
});
}
return mip;
}
public struct MacIpPair
{
public string MacAddress;
public string IpAddress;
}
using System.Net;
using System.Runtime.InteropServices;
[DllImport("iphlpapi.dll", ExactSpelling = true)]
public static extern int SendARP(int DestIP, int SrcIP, [Out] byte[] pMacAddr, ref int PhyAddrLen);
try
{
IPAddress hostIPAddress = IPAddress.Parse("XXX.XXX.XXX.XX");
byte[] ab = new byte[6];
int len = ab.Length,
r = SendARP((int)hostIPAddress.Address, 0, ab, ref len);
Console.WriteLine(BitConverter.ToString(ab, 0, 6));
}
catch (Exception ex) { }
或使用电脑名称
try
{
Tempaddr = System.Net.Dns.GetHostEntry("DESKTOP-xxxxxx");
}
catch (Exception ex) { }
byte[] ab = new byte[6];
int len = ab.Length, r = SendARP((int)Tempaddr.AddressList[1].Address, 0, ab, ref len);
Console.WriteLine(BitConverter.ToString(ab, 0, 6));
只是一种更高效的已接受方法的改进版本。
public string GetMacByIp( string ip )
{
var pairs = this.GetMacIpPairs();
foreach( var pair in pairs )
{
if( pair.IpAddress == ip )
return pair.MacAddress;
}
throw new Exception( $"Can't retrieve mac address from ip: {ip}" );
}
public IEnumerable<MacIpPair> GetMacIpPairs()
{
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
pProcess.StartInfo.FileName = "arp";
pProcess.StartInfo.Arguments = "-a ";
pProcess.StartInfo.UseShellExecute = false;
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.StartInfo.CreateNoWindow = true;
pProcess.Start();
string cmdOutput = pProcess.StandardOutput.ReadToEnd();
string pattern = @"(?<ip>([0-9]{1,3}\.?){4})\s*(?<mac>([a-f0-9]{2}-?){6})";
foreach( Match m in Regex.Matches( cmdOutput, pattern, RegexOptions.IgnoreCase ) )
{
yield return new MacIpPair()
{
MacAddress = m.Groups[ "mac" ].Value,
IpAddress = m.Groups[ "ip" ].Value
};
}
}
public struct MacIpPair
{
public string MacAddress;
public string IpAddress;
}
使用SharpPCap,它可以在Windows和Linux上运行
public string getMacAdress(string ip){
LibPcapLiveDeviceList devices = LibPcapLiveDeviceList.Instance;//list all your network cards
ARP arp = new ARP(devices[0]);//select the first network card by default
IPAddress ip = IPAddress.Parse(ip);
PhysicalAddress macAdress = arp.Resolve(ip);
return macAdress.ToString();
}
dotnet add package ArpLookup
之后,使用起来非常简单。using System.Net.NetworkInformation;
using ArpLookup;
// ...
PhysicalAddress mac = Arp.Lookup(IPAddress.Parse("1.2.3.4"));
PhysicalAddress mac = await Arp.LookupAsync(IPAddress.Parse("1.2.3.4"));