遠程喚醒技術原理

遠程喚醒技術(Wake On LAN)是通過給支持WOL標準的網卡,廣播一個特定格式的數據包,由網卡喚醒停機狀態中的計算機的這麼一種技術。常用於遠程喚醒網絡服務器。

數據包格式:6個0xFF字節+16次目標機器的MAC地址

如需要喚醒MAC地址爲00:1E:67:03:35:BD的計算機,數據包數據如下(十六進制):
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD 0x00 0x1E 0x67 0x03 0x35 0xBD

附一段簡單的C代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>

#define PORT 12345

int main(int argc, char **argv) {
	if (argc < 2) {
		printf("Usage: wake mac1 mac2 mac3 ...\n");
		exit(1);
	}
	int s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s == -1) {
		perror("socket");
		exit(1);
	}
	int optval = 1;
	int ret = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(int)); 
	if (ret == -1) {
		perror("setsockopt");
		exit(1);
	}
	struct sockaddr_in addr;
	bzero(&addr, sizeof(addr));
	addr.sin_family = AF_INET;
	//addr.sin_addr.s_addr = inet_addr("192.168.0.23");
	addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
	addr.sin_port = htons(PORT);
	int i, j, k;
	char buf[6 + 16 * 6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
	char dst[2];
	for (i = 1; i < argc; ++i) {
		if (strlen(argv[i]) != 17) {
			printf("Invalid mac address %s!\n", argv[i]);
			continue;
		}
		j = 5;
		buf[++j] = (char)strtol(strncpy(dst, argv[i]     , 2), NULL, 16);
		buf[++j] = (char)strtol(strncpy(dst, argv[i] +  3, 2), NULL, 16);
		buf[++j] = (char)strtol(strncpy(dst, argv[i] +  6, 2), NULL, 16);
		buf[++j] = (char)strtol(strncpy(dst, argv[i] +  9, 2), NULL, 16);
		buf[++j] = (char)strtol(strncpy(dst, argv[i] + 12, 2), NULL, 16);
		buf[++j] = (char)strtol(strncpy(dst, argv[i] + 15, 2), NULL, 16);
		k = 2;
		do {
			memcpy(buf + k * 6, buf + 6, 6);
		} while (++k < 18);
		int len = sendto(s, buf, sizeof(buf), 0, (struct sockaddr*)&addr, sizeof(addr));
		if (len == -1) {
			perror("sendto");
		} else {
			printf("Wake %s OK!\n", argv[i]);
		}
	}
	return 0;
}

參考資料:

http://en.wikipedia.org/wiki/Wake-on-LAN


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章