小试网络唤醒协议Wake On LAN

2020-09-05  本文已影响0人  叶迎宪

首先,被唤醒的电脑应处于睡眠状态,而不是关机状态。处于睡眠状态的电脑,网卡仍然是通电的。

先用ubuntu上面现成的工具尝试一下

apt install wakeonlan
wakeonlan b4:2e:99:c1:25:dc

后面这堆是被唤醒电脑网卡的mac地址。这个wakeonlan会自动向255.255.255.255的地址广播WOL数据包。一试就成功了

然后就是自己模仿WOL协议,实现的一小段程序

#include <WS2tcpip.h>
#include <stdio.h>

#define MAGIC_LEN 17 * 6

#pragma comment(lib, "Ws2_32.lib")

int SendMagicPacket(char *dst_ip, int dst_port, char *dst_mac)
{
    char magic_packet[MAGIC_LEN];
    char bin_mac[6];
    char *buf;
    int fd;
    struct sockaddr_in dst_addr;
    int send_bytes;
    int i, tmp;

    for (i = 0; i < 6; i++)
    {
        sscanf(dst_mac, "%02x", &tmp);
        bin_mac[i] = tmp & 0xff;
        dst_mac += 3;
    }

    memset(magic_packet, 0xff, 6);
    buf = magic_packet + 6;

    for (i = 0; i < 16; i++)
    {
        memcpy(buf, bin_mac, 6);
        buf += 6;
    }

    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        printf("socket fail\n");
        return -1;
    }

    memset(&dst_addr, 0, sizeof(struct sockaddr_in));
    dst_addr.sin_family = AF_INET;
    dst_addr.sin_addr.s_addr = inet_addr(dst_ip);
    dst_addr.sin_port = htons(dst_port);

    if ((send_bytes = sendto(fd, magic_packet, MAGIC_LEN, 0,
        (struct sockaddr *)&dst_addr, sizeof(struct sockaddr))) == -1) {
        printf("sendto fail, errno=%d\n", errno);
        return -1;
    }

    closesocket(fd);
    return 0;
}

int main()
{
    WSADATA wsa = { 0 };
    WSAStartup(MAKEWORD(2, 2), &wsa);

    char dst_ip[] = "192.168.3.255";
    int port = 9;
    char dst_mac[] = "b4:2e:99:c1:25:dc";

    SendMagicPacket(dst_ip, port, dst_mac);
}

由于这个WOL协议确实很简单,先是6个字节的0xFF,然后就是16次6字节的MAC地址,往广播地址的9端口发送,一试也成功了。

上一篇 下一篇

猜你喜欢

热点阅读