网络唤醒
柠柠送了我一个树莓派,初步打算先拿来做连接局域网设备的跳板机(基于frp实现),顺便给台式机进行网络唤醒,以便出门时也能随时使用。
原理非常简单,在局域网内广播Magic Packet即可,Magic Packet的格式很简单,FFFFFFFFFFFF
后重复目标主机的MAC地址即可。百度百科的网络唤醒词条有介绍:
初步打算利用Java实现,核心部分代码如下:
StringBuilder sb = new StringBuilder();
sb.append("FFFFFFFFFFFF");
for (int i = 0; i < 16; i++) {
sb.append(mac);
}
String raw = sb.toString();
byte[] bytes = new byte[102];
for (int i = 0; i < 204; i += 2) {
String temp = raw.substring(i, i + 2);
bytes[i / 2] = (byte) Integer.parseInt(temp, 16);
}
最后将bytes
广播即可。
最后,记着打开网卡网络唤醒的开关:
测试
代码打包成jar包,扔到树莓派上运行,电脑用WireShark抓包测试。
树莓派执行:
抓包结果:
成功抓到包,格式无误,测试完成。
完整代码:
package xyz.cambria.wol;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.*;
import java.util.Properties;
/**
* @Author Cambria
* @creat 2021/1/25 22:34
*/
public class WakeOnLan {
public static void main(String[] args) {
Properties properties = new Properties();
try {
properties.load(new FileInputStream("WOL.properties"));
} catch (Exception e) {
System.out.println("无法读取配置文件\"mac.properties\"");
return;
}
String mac = properties.getProperty("mac");
String address = properties.getProperty("address");
if (mac == null || mac == "" || address == null || address == ""){
System.out.println("配置文件格式错误,应为:\n\tmac = #{mac}\n\taddress = #{address}");
return;
}
StringBuilder sb = new StringBuilder();
sb.append("FFFFFFFFFFFF");
for (int i = 0; i < 16; i++) {
sb.append(mac);
}
String raw = sb.toString();
byte[] bytes = new byte[102];
for (int i = 0; i < 204; i += 2) {
String temp = raw.substring(i, i + 2);
bytes[i / 2] = (byte) Integer.parseInt(temp, 16);
}
DatagramPacket packet = null;
try {
packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(address), 2333);
} catch (UnknownHostException e) {
System.out.println("IP地址格式错误");
return;
}
DatagramSocket socket = null;
try {
socket = new DatagramSocket();
} catch (SocketException e) {
System.out.println("创建socket出错");
return;
}
try {
socket.send(packet);
} catch (IOException e) {
System.out.println("IO错误,无法发送数据");
return;
}
socket.close();
System.out.println("唤醒包已发送");
return;
}
}
没错,这玩意早就在用了,不过一直是放到NAS上跑有些不伦不类。现在拿出来重新扔到树莓派上