golang—实现wake on lan

  • Post author:
  • Post category:golang




实现逻辑

就是通过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
}



版权声明:本文为newbieJ原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。