使用C#在局域网上实现唤醒的最好方法是什么?
这种功能是局域网环境中的机器所需要的(而不是通过互联网)。该方法需要足够的鲁棒性来处理防火墙和其他此类问题。另外,对于不支持此功能或禁用此功能的系统,是否有其他选择?
主要目标是唤醒局域网上的机器(从关机/hibernate状态),这是使用C#编程的。
请指点。
PS:我遇到了以下情况:
然而,我对此并不熟悉,因此无法理解这些解决方案是否足够全面。如果有人能推荐以下任何一篇文章,那会有帮助的。
发布于 2009-05-14 07:27:06
对于WOL问题,您必须澄清三个问题才能开始工作:
正如您在网上已经发现的,对于C#中的第一个问题,有几种解决方案(在浏览链接之后,我将从第一个问题开始)。
第二个是您只能通过配置网络适配器来实现的。只需打开设备管理器,查看网络适配器的属性,如果存在这样的选项,以及是否可以启用它。这是无法编程的,因为每个网络适配器都有另一个该功能的实现,以及如何启用它。
第三个问题也不能用C#解决。这是一个纯粹的网络问题,您必须配置您的路由器、网关、ids系统等,以便允许这样的数据包从发送方流向接收方。由于WOL包始终是一个广播包(dest-ip 255.255.255),它不会离开您的本地网络,并且总是从路由器、网关或网络之间的任何其他桥接(例如vpns等)丢弃。
最后但并非最不重要的,我只想提醒你,第一个问题可以分为一些较小的包,但据我所能看到,这些问题都是由你提供的链接。
发布于 2019-09-21 18:30:52
很老的问题,我知道,但仍然有效。由于我没有在接受的答案中看到任何C#,所以我编写了自己的“唤醒局域网”代码。
我的目标是使一个通用的、简单的、通用的Wake On Lan class :
如何使用:
您所需要的只是您想要唤醒的计算机上的有线 nic的MAC地址。任何标准的十六进制表示都可以。然后按如下方式调用代码:
string mac = "01-02-03-04-05-06";
await WOL.WakeOnLan(mac);,这是一个类:
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
public static class WOL
{
public static async Task WakeOnLan(string macAddress)
{
byte[] magicPacket = BuildMagicPacket(macAddress);
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces().Where((n) =>
n.NetworkInterfaceType != NetworkInterfaceType.Loopback && n.OperationalStatus == OperationalStatus.Up))
{
IPInterfaceProperties iPInterfaceProperties = networkInterface.GetIPProperties();
foreach (MulticastIPAddressInformation multicastIPAddressInformation in iPInterfaceProperties.MulticastAddresses)
{
IPAddress multicastIpAddress = multicastIPAddressInformation.Address;
if (multicastIpAddress.ToString().StartsWith("ff02::1%", StringComparison.OrdinalIgnoreCase)) // Ipv6: All hosts on LAN (with zone index)
{
UnicastIPAddressInformation unicastIPAddressInformation = iPInterfaceProperties.UnicastAddresses.Where((u) =>
u.Address.AddressFamily == AddressFamily.InterNetworkV6 && !u.Address.IsIPv6LinkLocal).FirstOrDefault();
if (unicastIPAddressInformation != null)
{
await SendWakeOnLan(unicastIPAddressInformation.Address, multicastIpAddress, magicPacket);
break;
}
}
else if (multicastIpAddress.ToString().Equals("224.0.0.1")) // Ipv4: All hosts on LAN
{
UnicastIPAddressInformation unicastIPAddressInformation = iPInterfaceProperties.UnicastAddresses.Where((u) =>
u.Address.AddressFamily == AddressFamily.InterNetwork && !iPInterfaceProperties.GetIPv4Properties().IsAutomaticPrivateAddressingActive).FirstOrDefault();
if (unicastIPAddressInformation != null)
{
await SendWakeOnLan(unicastIPAddressInformation.Address, multicastIpAddress, magicPacket);
break;
}
}
}
}
}
static byte[] BuildMagicPacket(string macAddress) // MacAddress in any standard HEX format
{
macAddress = Regex.Replace(macAddress, "[: -]", "");
byte[] macBytes = new byte[6];
for (int i = 0; i < 6; i++)
{
macBytes[i] = Convert.ToByte(macAddress.Substring(i * 2, 2), 16);
}
using (MemoryStream ms = new MemoryStream())
{
using (BinaryWriter bw = new BinaryWriter(ms))
{
for (int i = 0; i < 6; i++) //First 6 times 0xff
{
bw.Write((byte)0xff);
}
for (int i = 0; i < 16; i++) // then 16 times MacAddress
{
bw.Write(macBytes);
}
}
return ms.ToArray(); // 102 bytes magic packet
}
}
static async Task SendWakeOnLan(IPAddress localIpAddress, IPAddress multicastIpAddress, byte[] magicPacket)
{
using (UdpClient client = new UdpClient(new IPEndPoint(localIpAddress, 0)))
{
await client.SendAsync(magicPacket, magicPacket.Length, multicastIpAddress.ToString(), 9);
}
}
}的工作方式:
代码的工作方式是枚举所有“up”并连接到您的网络的网卡(通常只有一张)。它将使用多播将“魔术包”发送给所有连接的网络,这可以同时使用ipv4和ipv6 (不要担心淹没您的网络,它只有102个字节)。
要工作,您想要唤醒的计算机必须有有线连接(无线计算机不能唤醒,因为它们在关闭时没有连接到任何网络)。发送数据包的计算机可以无线连接。
防火墙通常没有问题,因为计算机关闭了,因此防火墙没有激活。
您必须确保'Wake on lan' enabled 是计算机的 BIOS 和网卡上的。
.Net 6的更新(以及bug修复):
修正了一个错误,如果Ipv6在发送数据包的计算机上运行,而不是在那个计算机上运行,那么应该被唤醒,那么它就不会尝试Ipv4 (这在上面的代码中是固定的)。
下面是在.Net 6上工作的代码(借用了@Oskar berg的代码)- implicit usings turned on
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text.RegularExpressions;
public static class WOL
{
public static async Task WakeOnLan(string macAddress)
{
byte[] magicPacket = BuildMagicPacket(macAddress);
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces().Where((n) =>
n.NetworkInterfaceType != NetworkInterfaceType.Loopback && n.OperationalStatus == OperationalStatus.Up))
{
IPInterfaceProperties iPInterfaceProperties = networkInterface.GetIPProperties();
foreach (MulticastIPAddressInformation multicastIPAddressInformation in iPInterfaceProperties.MulticastAddresses)
{
IPAddress multicastIpAddress = multicastIPAddressInformation.Address;
if (multicastIpAddress.ToString().StartsWith("ff02::1%", StringComparison.OrdinalIgnoreCase)) // Ipv6: All hosts on LAN (with zone index)
{
UnicastIPAddressInformation? unicastIPAddressInformation = iPInterfaceProperties.UnicastAddresses.Where((u) =>
u.Address.AddressFamily == AddressFamily.InterNetworkV6 && !u.Address.IsIPv6LinkLocal).FirstOrDefault();
if (unicastIPAddressInformation != null)
{
await SendWakeOnLan(unicastIPAddressInformation.Address, multicastIpAddress, magicPacket);
}
}
else if (multicastIpAddress.ToString().Equals("224.0.0.1")) // Ipv4: All hosts on LAN
{
UnicastIPAddressInformation? unicastIPAddressInformation = iPInterfaceProperties.UnicastAddresses.Where((u) =>
u.Address.AddressFamily == AddressFamily.InterNetwork && !iPInterfaceProperties.GetIPv4Properties().IsAutomaticPrivateAddressingActive).FirstOrDefault();
if (unicastIPAddressInformation != null)
{
await SendWakeOnLan(unicastIPAddressInformation.Address, multicastIpAddress, magicPacket);
}
}
}
}
}
static byte[] BuildMagicPacket(string macAddress) // MacAddress in any standard HEX format
{
macAddress = Regex.Replace(macAddress, "[: -]", "");
byte[] macBytes = Convert.FromHexString(macAddress);
IEnumerable<byte> header = Enumerable.Repeat((byte)0xff, 6); //First 6 times 0xff
IEnumerable<byte> data = Enumerable.Repeat(macBytes, 16).SelectMany(m => m); // then 16 times MacAddress
return header.Concat(data).ToArray();
}
static async Task SendWakeOnLan(IPAddress localIpAddress, IPAddress multicastIpAddress, byte[] magicPacket)
{
using UdpClient client = new(new IPEndPoint(localIpAddress, 0));
await client.SendAsync(magicPacket, magicPacket.Length, new IPEndPoint(multicastIpAddress, 9));
}
}发布于 2021-01-01 12:48:03
我正在尝试Poul的答案,但没能唤醒我的目标计算机。在验证了第三方应用程序WakeMeOnLan实际上能够唤醒我的目标计算机之后,我编写了以下代码:
void SendWakeOnLan(PhysicalAddress target)
{
var header = Enumerable.Repeat(byte.MaxValue, 6);
var data = Enumerable.Repeat(target.GetAddressBytes(), 16).SelectMany(mac => mac);
var magicPacket = header.Concat(data).ToArray();
using var client = new UdpClient();
client.Send(magicPacket, magicPacket.Length, new IPEndPoint(IPAddress.Broadcast, 9));
}用法:
只需输入目标计算机的mac地址,如下所示:
SendWakeOnLan(PhysicalAddress.Parse("0A-0B-0C-0D-0E-0F"));我认为这个答案和Poul的回答的主要区别是,这个代码使用的是IPv4广播而不是IPv6 4/IPv6 6上的多播,也许我的网络设备没有正确地处理/设置多播。
https://stackoverflow.com/questions/861873
复制相似问题