实现逻辑
就是通过UDP向广播地址255.255.255.255:9发送一个称为“魔术包”的数据包。被唤醒主机关机之后需要和程序所在主机通过网线连接,才能收到这个数据包。被唤醒主机收到之后就会开机。
配置需要被唤醒的主机
我的台式主机试DELL的,dell官网有相关的配置方法,其他的可能有区别需要查询
我的主机配置方法
实施唤醒操作的程序
要注意的是
:程序所在的主机,要确保一定有一次的数据包是通过那个有限网卡发出去的,可以在程序中指定从哪个网卡发出,或者控制主机的无线网络,或者每个网卡都发一次
指定网卡发送UDP数据包
var help = `
环境说明:
1. 被唤醒主机要支持Wake on Lan功能且已开启该功能
2. 被唤醒主机在关机时应该是有线连接
3. 请确保该程序与被唤醒主机在同一局域网中
参数说明:
-mac 被唤醒主机的MAC地址 (必须输入)
-nic 指定网卡发送唤醒魔包
使用说明:
wol -mac 11:22:33:44:55:66 -nic eno1
注意事项:
1. 路由器设备或有些主机有多张网卡, 如果不指定网卡唤醒魔包可能到达不了被唤醒主机
2. MAC地址的格式可以是以下几种形式
11:22:33:44:55:66 或
11-22-33-44-55-66 或
11:22-33:44:55-66 或
112233445566
`
func main() {
err := wakeNew()
fmt.Println("wakeNew err = ", err)
}
func wakeNew() error {
macAddr := flag.String("mac", "xx:xx:xx:xx:xx:xx", help)//被唤醒主机的MAC地址,这里通过一条网线连接的,可以在网络适配器看见整个以太网地址
nic := flag.String("nic", "以太网 2", help)
flag.Parse()
if len(*macAddr) == 0 {
return errors.New(fmt.Sprintf("%s\n", help))
}
hw := strings.Replace(strings.Replace(*macAddr, ":", "", -1), "-", "", -1)
if len(hw) != 12 {
return errors.New(fmt.Sprintf("MAC: [%s] 输入不正确.\n", *macAddr))
}
macBytes, err := hex.DecodeString(hw)
if err != nil {
fmt.Println("DecodeString err = ", err)
return err
}
// 构造 Magic Packet 数据包
var magicPacket bytes.Buffer
for i := 0; i < 6; i++ {
err := magicPacket.WriteByte(0xff)
if err != nil {
fmt.Println("WriteByte err = ", err)
}
}
for i := 0; i < 16; i++ {
_, err = magicPacket.Write(macBytes)
if err != nil {
fmt.Println("magicPacket Write err = ", err)
}
}
sender := net.UDPAddr{}
if len(*nic) != 0 {
ip, err := interfaceIPv4ByName(*nic)
if err != nil {
err = errors.New(fmt.Sprintf("网卡[%s]错误: %s", *nic, err))
return err
}
sender.IP = ip
}
// 发送 Magic Packet
target , err := net.ResolveUDPAddr("udp", "255.255.255.255:9")
if err != nil {
fmt.Println("ResolveUDPAddr err = ", err)
return err
}
//也可以这样写
// target := net.UDPAddr{
// IP: net.IPv4bcast,
// Port: 9,
// }
conn, err := net.DialUDP("udp", &sender, &target)
if err != nil {
fmt.Println("DialUDP err = ", err)
return err
}
_, err = conn.Write(magicPacket.Bytes())
if err != nil {
fmt.Println("conn.Write err = ", err)
return err
}
fmt.Println("Wake-on-LAN packet sent!")
return nil
}