gpt4 book ai didi

c# - 使用 C# 在 LAN 上唤醒

转载 作者:太空狗 更新时间:2023-10-29 22:21:10 25 4
gpt4 key购买 nike

使用 C# 实现局域网唤醒的最佳方式是什么?

在 LAN 环境中(而不是在 Internet 上)的机器需要该功能。该方法需要足够健壮以应对防火墙和其他此类问题。此外,对于不支持或禁用此功能的系统,是否有替代方案?

主要目标 - 通过 LAN 唤醒机器(从关机/休眠状态) - 这将使用 C# 进行编程。

请指导。

PS:我遇到过以下情况:

  1. http://blog.memos.cz/index.php/team/2008/06/12/wake-on-lan-in-csharp
  2. http://community.bartdesmet.net/blogs/bart/archive/2006/04/02/3858.aspx
  3. http://www.codeproject.com/KB/IP/cswol.aspx

但是,我是新手,因此无法确定解决方案是否足够全面。如果有人可以推荐阅读上述任何一篇文章,那将会有所帮助。

最佳答案

很老的问题,我知道,但仍然有效。由于我在接受的答案中没有看到任何 C#,因此我编写了自己的“Wake On Lan”代码。

我的目标是制作一个通用且简单的 Wake On Lan class 那:

  • 适用于 ipv4ipv6双栈
  • 使用连接到不同网络(两台计算机)的一个或多个网卡 (NICS)。
  • 以任何标准的十六进制格式与 macaddress 一起工作。
  • 使用 多播 工作(使用多个 NIC 时,Windows 中的广播存在错误,使用 ipv6 时不支持)。

使用方法:

您所需要的只是要唤醒的计算机上有线 网卡的MAC 地址。任何标准的十六进制表示都可以。然后像这样调用代码:

string mac = "01-02-03-04-05-06";
await WOL.WakeOnLan(mac);

这是类(class):

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);
}
}
}

工作原理:

该代码通过枚举所有“启动”并连接到您的网络的网卡(通常只有一个)来工作。它会使用多播向所有连接的网络发送“魔法数据包”,它适用于 ipv4 和 ipv6(不用担心淹没您的网络,它只有 102 字节)。

要工作,您想要唤醒的计算机必须具有有线连接(无线计算机无法被唤醒,因为它们没有连接到任何网络,当它们连接时离开)。发送数据包的计算机可以无线连接。

防火墙通常没有问题,因为计算机已关闭,因此防火墙未处于事件状态。

您必须确保 'Wake on lan'enabled在电脑的BIOS和网卡上。

.Net 6 的更新(和错误修复):

修复了一个错误,如果 Ipv6 在发送数据包的计算机上运行,​​而不是在应该被唤醒的计算机上运行,​​那么它不会尝试 Ipv4(这在上面的代码中已修复)。

这是适用于 .Net 6 的代码(借用了@Oskar Sjô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));
}
}

关于c# - 使用 C# 在 LAN 上唤醒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/861873/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com