如何在 Delphi XE6 中使用 Magic packet 和 Indy 创建局域网唤醒应用程序?
How to create Wake-on-LAN app using Magic packet and Indy in Delphi XE6?
环境
OS: Windows 10 专业版 64 位
IDE: Delphi XE6 + 更新 1
目标
在Delphi XE6 中创建一个应用程序,通过Indy 组件发送Magic packet 以实现局域网唤醒本地服务器。服务器已经过测试,能够从 Linux 客户端唤醒。
请注意,我想创建自己的解决方案,没有任何应用建议。谢谢。
魔法包
引用 Wikipedia article 的部分内容:
The magic packet is a broadcast frame containing anywhere within its payload 6 bytes of all 255 (FF FF FF FF FF FF in hexadecimal), followed by sixteen repetitions of the target computer's 48-bit MAC address, for a total of 102 bytes.
基本版本
我从 this page 获得了基本版本。
作者没有提到他使用的是哪个版本Delphi,我们假设是一个旧版本。
我会引用它,以防页面变得不可用,保持不变:
procedure WakeOnLan(const AMacAddress : string);
type
TMacAddress = array [1..6] of byte;
TWakeRecord = packed record
Waker : TMACAddress;
MAC : array[0..15] of TMACAddress;
end;
var i : integer;
WR : TWakeRecord;
MacAddress : TMacAddress;
UDP : TIdUDPClient;
sData : string;
begin
// Convert MAC string into MAC array
fillchar(MacAddress,SizeOf(TMacAddress),0);
sData := trim(AMacAddress);
if length(sData) = 17 then begin
for i := 1 to 6 do begin
MacAddress[i] := StrToIntDef('$' + copy(sData,1,2),0);
sData := copy(sData,4,17);
end;
end;
for i := 1 To 6 do WR.Waker[i] := $FF;
for i := 0 to 15 do WR.MAC[i] := MacAddress;
// Create UDP and Broadcast data structure
UDP := TIdUDPClient.Create(nil);
UDP.Host := '255.255.255.255';
UDP.Port := 32767;
UDP.BroadCastEnabled := true;
UDP.SendBuffer(WR,SizeOf(TWakeRecord));
UDP.BroadcastEnabled := false;
UDP.Free;
end;
但是DelphiXE6的编译器在线报错:
UDP.SendBuffer(WR,SizeOf(TWakeRecord));
上面写着:
[dcc64 Error] main.pas(73): E2250 There is no overloaded version of 'SendBuffer' that can be called with these arguments
我的版本
为了更好的可读性重写了上面的代码 + 我已经尝试了各种方法,这些方法都不会编译以这个结尾,虽然它确实可以编译,但它显然不起作用(不唤醒服务器)。
procedure WakeOnLan(const AMacAddress: string);
type
TMacAddress = array [1..6] of Byte;
TWakeRecord = packed record
Waker : TMACAddress;
MAC : array [0..15] of TMacAddress;
end;
var
I : Integer;
WR : TWakeRecord;
MacAddress : TMacAddress;
UDPClient : TIdUDPClient;
sData : string;
begin
FillChar(MacAddress, SizeOf(TMacAddress), 0);
sData := Trim(AMacAddress);
if Length(sData) = 17 then begin
for I := 1 to 6 do begin
MacAddress[I] := StrToIntDef('$' + Copy(sData, 1, 2), 0);
sData := Copy(sData, 4, 17);
end;
end;
for I := 1 to 6 do WR.Waker[I] := $FF;
for I := 0 to 15 do WR.MAC[I] := MacAddress;
UDPClient := TIdUDPClient.Create(nil);
try
// UDP.Host := '255.255.255.255';
// UDP.Port := 32767;
UDPClient.BroadCastEnabled := True;
UDPClient.Broadcast(RawToBytes(WR, SizeOf(TWakeRecord)), 7);
// UDP.SendBuffer(RawToBytes(WR, SizeOf(TWakeRecord)));
UDPClient.BroadcastEnabled := False;
finally
UDPClient.Free;
end;
end;
编辑1
我根本不想使用任何 IP 地址,只需要纯 MAC 地址即可。
这段代码对我有用,看一下SendBuffer函数的参数(服务器,端口,缓冲区):
UDP.IPVersion := Id_IPv4;
UDP.BroadCastEnabled := True;
UDP.SendBuffer('192.168.1.255', 9, RawToBytes(WR, SizeOf(WR)));
UDP.BroadCastEnabled := False;
注意广播地址'255.255.255.255'可能无效,你应该限制广播的范围作为示例。
原始代码是为 Indy 9 编写的。Indy 10 等效代码看起来更像这样:
UDPClient := TIdUDPClient.Create(nil);
try
UDP.Host := '255.255.255.255';
UDP.Port := 32767;
UDP.IPVersion := Id_IPv4;
UDP.BroadcastEnabled := True;
UDP.SendBuffer(RawToBytes(WR, SizeOf(WR)));
finally
UDP.Free;
end;
或者:
UDPClient := TIdUDPClient.Create(nil);
try
UDP.IPVersion := Id_IPv4;
UDP.BroadCastEnabled := True;
UDP.SendBuffer('255.255.255.255', 32767, RawToBytes(WR, SizeOf(WR)));
finally
UDP.Free;
end;
或者:
UDP := TIdUDPClient.Create(nil);
try
UDP.IPVersion := Id_IPv4;
UDP.Broadcast(RawToBytes(WR, SizeOf(WR)), 32767);
finally
UDP.Free;
end;
环境
OS: Windows 10 专业版 64 位
IDE: Delphi XE6 + 更新 1
目标
在Delphi XE6 中创建一个应用程序,通过Indy 组件发送Magic packet 以实现局域网唤醒本地服务器。服务器已经过测试,能够从 Linux 客户端唤醒。
请注意,我想创建自己的解决方案,没有任何应用建议。谢谢。
魔法包
引用 Wikipedia article 的部分内容:
The magic packet is a broadcast frame containing anywhere within its payload 6 bytes of all 255 (FF FF FF FF FF FF in hexadecimal), followed by sixteen repetitions of the target computer's 48-bit MAC address, for a total of 102 bytes.
基本版本
我从 this page 获得了基本版本。
作者没有提到他使用的是哪个版本Delphi,我们假设是一个旧版本。
我会引用它,以防页面变得不可用,保持不变:
procedure WakeOnLan(const AMacAddress : string);
type
TMacAddress = array [1..6] of byte;
TWakeRecord = packed record
Waker : TMACAddress;
MAC : array[0..15] of TMACAddress;
end;
var i : integer;
WR : TWakeRecord;
MacAddress : TMacAddress;
UDP : TIdUDPClient;
sData : string;
begin
// Convert MAC string into MAC array
fillchar(MacAddress,SizeOf(TMacAddress),0);
sData := trim(AMacAddress);
if length(sData) = 17 then begin
for i := 1 to 6 do begin
MacAddress[i] := StrToIntDef('$' + copy(sData,1,2),0);
sData := copy(sData,4,17);
end;
end;
for i := 1 To 6 do WR.Waker[i] := $FF;
for i := 0 to 15 do WR.MAC[i] := MacAddress;
// Create UDP and Broadcast data structure
UDP := TIdUDPClient.Create(nil);
UDP.Host := '255.255.255.255';
UDP.Port := 32767;
UDP.BroadCastEnabled := true;
UDP.SendBuffer(WR,SizeOf(TWakeRecord));
UDP.BroadcastEnabled := false;
UDP.Free;
end;
但是DelphiXE6的编译器在线报错:
UDP.SendBuffer(WR,SizeOf(TWakeRecord));
上面写着:
[dcc64 Error] main.pas(73): E2250 There is no overloaded version of 'SendBuffer' that can be called with these arguments
我的版本
为了更好的可读性重写了上面的代码 + 我已经尝试了各种方法,这些方法都不会编译以这个结尾,虽然它确实可以编译,但它显然不起作用(不唤醒服务器)。
procedure WakeOnLan(const AMacAddress: string);
type
TMacAddress = array [1..6] of Byte;
TWakeRecord = packed record
Waker : TMACAddress;
MAC : array [0..15] of TMacAddress;
end;
var
I : Integer;
WR : TWakeRecord;
MacAddress : TMacAddress;
UDPClient : TIdUDPClient;
sData : string;
begin
FillChar(MacAddress, SizeOf(TMacAddress), 0);
sData := Trim(AMacAddress);
if Length(sData) = 17 then begin
for I := 1 to 6 do begin
MacAddress[I] := StrToIntDef('$' + Copy(sData, 1, 2), 0);
sData := Copy(sData, 4, 17);
end;
end;
for I := 1 to 6 do WR.Waker[I] := $FF;
for I := 0 to 15 do WR.MAC[I] := MacAddress;
UDPClient := TIdUDPClient.Create(nil);
try
// UDP.Host := '255.255.255.255';
// UDP.Port := 32767;
UDPClient.BroadCastEnabled := True;
UDPClient.Broadcast(RawToBytes(WR, SizeOf(TWakeRecord)), 7);
// UDP.SendBuffer(RawToBytes(WR, SizeOf(TWakeRecord)));
UDPClient.BroadcastEnabled := False;
finally
UDPClient.Free;
end;
end;
编辑1
我根本不想使用任何 IP 地址,只需要纯 MAC 地址即可。
这段代码对我有用,看一下SendBuffer函数的参数(服务器,端口,缓冲区):
UDP.IPVersion := Id_IPv4;
UDP.BroadCastEnabled := True;
UDP.SendBuffer('192.168.1.255', 9, RawToBytes(WR, SizeOf(WR)));
UDP.BroadCastEnabled := False;
注意广播地址'255.255.255.255'可能无效,你应该限制广播的范围作为示例。
原始代码是为 Indy 9 编写的。Indy 10 等效代码看起来更像这样:
UDPClient := TIdUDPClient.Create(nil);
try
UDP.Host := '255.255.255.255';
UDP.Port := 32767;
UDP.IPVersion := Id_IPv4;
UDP.BroadcastEnabled := True;
UDP.SendBuffer(RawToBytes(WR, SizeOf(WR)));
finally
UDP.Free;
end;
或者:
UDPClient := TIdUDPClient.Create(nil);
try
UDP.IPVersion := Id_IPv4;
UDP.BroadCastEnabled := True;
UDP.SendBuffer('255.255.255.255', 32767, RawToBytes(WR, SizeOf(WR)));
finally
UDP.Free;
end;
或者:
UDP := TIdUDPClient.Create(nil);
try
UDP.IPVersion := Id_IPv4;
UDP.Broadcast(RawToBytes(WR, SizeOf(WR)), 32767);
finally
UDP.Free;
end;