📜  使用 LAN 唤醒协议通过 Internet 远程打开 PC 的程序。

📅  最后修改于: 2022-05-13 01:57:03.448000             🧑  作者: Mango

使用 LAN 唤醒协议通过 Internet 远程打开 PC 的程序。

Wake-on-LAN (WoL) 是一种以太网或令牌环计算机网络标准,它允许计算机被网络消息打开或唤醒。

  • 该消息通常由连接到同一局域网的设备(例如智能手机)上执行的程序发送到目标计算机。
  • 也可以通过使用子网定向广播或 WOL 网关服务从另一个网络发起消息。
  • 等效术语包括 WAN 唤醒、远程唤醒、LAN 开机、LAN 开机、LAN 恢复、LAN 恢复和 LAN 唤醒。

工作原理

  • 局域网唤醒(“WOL”)是使用一种特殊设计的数据包实现的,称为魔术数据包,该数据包被发送到网络中的所有计算机,其中包括要被唤醒的计算机。
  • 魔术包包含目标计算机的 MAC 地址、内置在每个网络接口卡 (“NIC”) 或计算机中其他以太网设备中的识别号,使其能够在网络上被唯一识别和寻址。
  • 具有 LAN 唤醒功能的断电或关闭计算机将包含能够在系统断电时以低功耗模式“侦听”传入数据包的网络设备。
  • 如果接收到指向设备 MAC 地址的魔术包,NIC 会向计算机的电源或主板发出信号以启动系统唤醒,这与按下电源按钮的方式非常相似。
  • 魔术包在数据链路层(OSI 模型中的第 2 层)上发送,发送后,使用网络广播地址向给定网络上的所有连接设备广播;不使用 IP 地址(OSI 模型中的第 3 层)。

为了使 LAN 唤醒工作,部分网络接口需要保持打开状态。这消耗少量的待机功率,远低于正常工作功率。因此,在不需要时禁用 LAN 唤醒可以稍微降低已关闭但仍插入电源插座的计算机的功耗。

魔术包结构
魔术包是一个广播帧,在其有效负载中包含所有 255 个字节中的 6 个字节(十六进制的 FF FF FF FF FF FF),然后是目标计算机的 48 位 MAC 地址的 16 次重复,总共 102 个字节。
由于魔术包只扫描上面的字符串,并没有被完整的协议栈实际解析,它可以作为任何网络和传输层协议发送,尽管它通常作为 UDP 数据报发送到端口 0、7 ,或 9,或直接通过以太网作为 EtherType 0x0842。

标准魔术包具有以下基本限制:

  1. 需要目标计算机 MAC 地址(也可能需要 SecureOn 密码)。
  2. 不要提供交货确认。
  3. 可能无法在本地网络之外工作。
  4. 需要目标计算机上的 LAN 唤醒硬件支持。
  5. 大多数 802.11 无线接口在低功耗状态下不会保持链路,也无法接收魔术数据包。

Wake-on-LAN 实施设计得非常简单,并且可以由网络接口卡上的电路快速处理,并且功耗要求最低。因为 LAN 唤醒在 IP 协议层之下运行,所以需要 MAC 地址,这使得 IP 地址和 DNS 名称毫无意义。

C++
// C program to remotely Power On a PC over the
// internet using the Wake-on-LAN protocol.
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
int main()
{
    int i;
    unsigned char toSend[102],mac[6];
    struct sockaddr_in udpClient, udpServer;
    int broadcast = 1 ;
 
    // UDP Socket creation
    int udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
 
    // Manipulating the Socket
    if (setsockopt(udpSocket, SOL_SOCKET, SO_BROADCAST,
                  &broadcast, sizeof broadcast) == -1)
    {
        perror("setsockopt (SO_BROADCAST)");
        exit(EXIT_FAILURE);
    }
    udpClient.sin_family = AF_INET;
    udpClient.sin_addr.s_addr = INADDR_ANY;
    udpClient.sin_port = 0;
 
    //Binding the socket
    bind(udpSocket, (struct sockaddr*)&udpClient, sizeof(udpClient));
 
    for (i=0; i<6; i++)
        toSend[i] = 0xFF;
 
    // Let the MAC Address be ab:cd:ef:gh:ij:kl
    mac[0] = 0xab;  // 1st octet of the MAC Address
    mac[1] = 0xcd;  // 2nd octet of the MAC Address
    mac[2] = 0xef;  // 3rd octet of the MAC Address
    mac[3] = 0xgh;  // 4th octet of the MAC Address
    mac[4] = 0xij;  // 5th octet of the MAC Address
    mac[5] = 0xkl;  // 6th octet of the MAC Address
 
    for (i=1; i<=16; i++)
        memcpy(&toSend[i*6], &mac, 6*sizeof(unsigned char));
 
    udpServer.sin_family = AF_INET;
 
    // Broadcast address
    udpServer.sin_addr.s_addr = inet_addr("10.89.255.255");
    udpServer.sin_port = htons(9);
 
    sendto(udpSocket, &toSend, sizeof(unsigned char) * 102, 0,
             (struct sockaddr*)&udpServer, sizeof(udpServer));
    return 0;
}


输出:

This program will power on the switched-off PC
whose MAC Address is used in this program (the 
PC and the Host computer must be connected over
LAN).