首先,被唤醒的电脑应处于睡眠状态,而不是关机状态。处于睡眠状态的电脑,网卡仍然是通电的。
先用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端口发送,一试也成功了。
网友评论