Русская Википедия:Wake-on-LAN

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Wake-on-LAN (WOL; в переводе с Шаблон:Lang-en — «пробуждение по [сигналу из] локальной сети») — технология, позволяющая удалённо включить компьютер посредством отправки через локальную сеть специальной последовательности байтов — пакета данных (так называемого Шаблон:Lang-en2 — «волшебного пакета», см. ниже). Этот пакет может быть вставлен в пакеты любых стандартных протоколов более высоких уровней, например, UDP или IPX.

Требования к компьютеру для работы с Wake-on-LAN

  • Компьютер с источником питания, соответствующим стандарту ATX 2.01, и материнской платой, поддерживающей Wake-on-LAN;
  • Сетевая плата (в виде платы расширения либо встроенная в материнскую плату) с поддержкой Wake-on-LAN;
  • Если используется внешняя (не встроенная в материнскую плату) сетевая плата, и хотя бы одна из этих плат не соответствуют стандарту PCI 2.2 или более позднему, то необходим также специальный трёхпроводной кабель для соединения разъёмов Wake-on-LAN на материнской и сетевой платах.
  • Как для интегрированного, так и для внешнего сетевого адаптера, как правило, требуется включение Wake-on-LAN в настройках BIOS материнской платы.

Кроме того, необходима возможность послать Шаблон:Lang-en2 управляемому компьютеру. Это можно сделать, например, с помощью другого компьютера с соответствующей программой (см. примеры ниже).

Принцип работы

Управляемый компьютер находится в дежурном режиме (Шаблон:Lang-en — режим, предусмотренный спецификацией ATX, при котором из всех выходных цепей блока питания активна только дежурная +5VSB) и выдаёт питание на микросхему BIOS и сетевой адаптер[1]. Сетевой адаптер находится в режиме пониженного энергопотребления, при этом его микроконтроллер анализирует все пакеты, приходящие на соответствующий MAC-адрес, ничего не отвечая на них. Если одним из пакетов окажется magic packet, сетевой адаптер выдаст сигнал на включение питания компьютера.

Magic packet

Шаблон:Lang-en — это специальная последовательность байтов, которую для нормального прохождения по локальным сетям можно вставить в пакеты транспортного уровня, не требующие установки соединения (например, протокол UDP или устаревший IPX). Обычно для Wake-on-LAN пакеты протоколов верхнего уровня рассылают широковещательно, так как в случае динамического присвоения адресов неизвестно, какой IP-адрес соответствует какому MAC-адресу. Однако, для корректного прохождения через маршрутизатор, запрещающий широковещательные пакеты, можно послать пакет по какому-то определённому адресу.

В начале пакета идет так называемая цепочка синхронизации: Шаблон:Num, равных 0xFF. Затем — MAC-адрес сетевой платы, повторённый Шаблон:Num. То есть, если бы адрес платы выглядел как 01:02:03:04:05:06, то магический пакет оказался бы таким:

FFFFFFFFFFFF010203040506
010203040506010203040506
010203040506010203040506
010203040506010203040506
010203040506010203040506
010203040506010203040506
010203040506010203040506
010203040506010203040506
010203040506

Примеры

Программы

Исходники

Задача написания программы, посылающей магический пакет, достаточно проста и часто дается как учебная при изучении основ работы с сетью. Ниже представлено два примера таких программ в исходных кодах: Шаблон:Начало скрытого блока

using System.Globalization;
using System.Net;
using System.Net.Sockets;

Console.Write("Enter MAC: ");
var data = MacToBytes("11-22-33-44-55-66");
using var client = new UdpClient();
client.Send(data, new(IPAddress.Broadcast, 9));

Span<byte> MacToBytes(string mac)
{
    Span<byte> data = new byte[102];
    
    data[..6].Fill(0xFF);
    for(var i = 0; i < 6; i++) 
        data[i+6] = byte.Parse(mac[(i*3)..(i*3+2)], NumberStyles.HexNumber);
    
    for(var i = 12; i < 102; i+=6) 
        data[6..12].CopyTo(data[i..(i+6)]);
    
    return data;
}

Шаблон:Конец скрытого блока Шаблон:Начало скрытого блока Адаптирован для версии Delphi7.

unit WOL;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent,IdComponent,IdUDPBase,IdUDPClient,IdGlobal,
  StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
  TMACAddress = packed record
    case integer of
    0: (s1,s2,s3,s4,s5,s6 : byte; );
    1: (cmp1:word; cmp2:integer;);
  end;
 
  TWakeupMagicPacket = packed record
    FillFF : array [0..5] of byte;
    Mac  : array [0..15] of TMACAddress;
  end;
 
function TryStrToMac(str:string; var mac:TMACAddress):boolean;
var a,b:integer;
const ToHex = '0123456789ABCDEF';
begin
  Result:=false;
  str:=AnsiUpperCase(trim(str));
  if length(str)<17 then begin
    mac.cmp1:=0;
    mac.cmp2:=0;
    exit;
  end;
  a:=pos(str[1],ToHex)-1; b:=pos(str[2],ToHex)-1;
  if((a>=0)and(b>=0)and(str[3]='-')) then mac.s1:=a*16+b else exit;
  a:=pos(str[4],ToHex)-1; b:=pos(str[5],ToHex)-1;
  if((a>=0)and(b>=0)and(str[6]='-')) then mac.s2:=a*16+b else exit;
  a:=pos(str[7],ToHex)-1; b:=pos(str[8],ToHex)-1;
  if((a>=0)and(b>=0)and(str[9]='-')) then mac.s3:=a*16+b else exit;
  a:=pos(str[10],ToHex)-1; b:=pos(str[11],ToHex)-1;
  if((a>=0)and(b>=0)and(str[12]='-')) then mac.s4:=a*16+b else exit;
  a:=pos(str[13],ToHex)-1; b:=pos(str[14],ToHex)-1;
  if((a>=0)and(b>=0)and(str[15]='-')) then mac.s5:=a*16+b else exit;
  a:=pos(str[16],ToHex)-1; b:=pos(str[17],ToHex)-1;
  if((a>=0)and(b>=0)) then mac.s6:=a*16+b else exit;
  Result:=true;
end;
 
function TryWakeUpComputer(const MacAddress: string):boolean;
var i      : integer;
    mac    : TMACAddress;
    pkt    : TWakeupMagicPacket;
begin
  Result := false;
  if not TryStrToMac(MacAddress,mac) then exit;
  FillChar(pkt.FillFF[0],SizeOf(pkt.FillFF),$FF);
  for i:=0 to High(pkt.Mac) do pkt.Mac[i]:=mac;
  with TIdUDPClient.Create(nil) do try
    BroadcastEnabled := True;
    Host := '255.255.255.255';
    Port := 9;
    SendBuffer(pkt,sizeof(pkt));
    Result := true;
  finally
    Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if not TryWakeUpComputer(Edit1.Text) then  \\Мак вида BC-AE-C5-8E-0A-2C
  begin
    // Do something...
showmessage('ERROR');
  end;
end;

Шаблон:Конец скрытого блока

Примечания

Шаблон:Примечания

  1. Некоторые компьютеры необходимо включить вручную хотя бы один раз после установки сетевой платы. При этом включении компьютер обнаружит сетевую плату и в дальнейшем запомнит, на какое именно устройство следует подавать питание. Другим возможным решением может быть установка в BIOS параметра Шаблон:Lang-en2 («пробуждаться после пропадания питания») в значение Шаблон:Lang-en2 («Вкл.»)