Wake-On-LAN简称WOL,是一种电源管理功能;如果存在网络活动,则允许设备将操作系统从待机或休眠模式中唤醒。Wake-On-LAN的实现,主要是向目标主机发送特殊格式的数据包,俗称魔术包(Magic Packet)。MagicPacket格式虽然只是AMD公司开发推广的技术,并非世界公认的标准,但是仍然受到很多网卡制造商的支持,因此许多具有网络唤醒功能的网卡都能与之兼容。

魔术包的格式

在Magic Packet内,每次都会先有连续6个"FF",即:FF FF FF FF FF FF(没有空格,这个只是为了方便阅读),在连续6个"FF"后则连续重复16次Mac地址。

假设你的网卡物理地址为00:15:17:53:d4:f9, 这段Magic Packet内容如下:

FFFFFFFFFFFF00151753d4f900151753d4f900151753d4f900151753d4f9
    00151753d4f900151753d4f900151753d4f900151753d4f900151753d4f9
    00151753d4f900151753d4f900151753d4f900151753d4f900151753d4f9
    00151753d4f900151753d4f9

使用工具测试

在windows的应用商店里面搜wake on lan,就会出现一些可用的工具:

我选择了第一个,下载后安装,然后打开,截图如下:

第一个设备名随便取,没有关系,第二个是mac地址,一定要正确。然后点击wake即可唤醒局域网中特定mac地址的设备。

广播地址

广播地址(Broadcast Address)是专门用于同时向网络中所有工作站进行发送的一个地址。在使用TCP/IP 协议的网络中,主机标识段host ID 为全1 的IP 地址为广播地址,广播的分组传送给host ID段所涉及的所有计算机。例如,对于10.1.1.0 (255.255.255.0 )网段,其广播地址为10.1.1.255 (255 即为2 进制的11111111 ),当发出一个目的地址为10.1.1.255 的分组(封包)时,它将被分发给该网段上的所有计算机。
广播地址主要有两类编辑
广播地址应用于网络内的所有主句

受限广播

它不被路由发送,但会被送到相同物理网段段上的所有主机
IP地址的网络字段和主机字段全为1就是地址255.255.255.255

直接广播

网络广播会被路由,并会发送到专门网络上的每台主机
IP地址的网络字段定义这个网络,主机字段通常全为1,如 192.168.10.255

java udp 编程的基础知识回顾

InetAddress类

它一个IP地址,它可以是IPV4或者IPV6,如果你想明确区分他们,你可以使用Inet4Address或者Inet6Address。但大部分情况下没有必有,这个类可以表示他们中的任何一个。

创建InetAddress实例的时候可以传入一个“主机名”,主机名可以通过getHostName()方法获得,但是也可以什么都不传。

该类提供以下方法:

  • getByName(String s):获得一个InetAddress 类的对象,该对象中含有主机的IP地址和域名,该对象用如下格式表示它包含的信息:www.sina.com.cn/202.108.37.40;
  • String getHostName():获取InetAddress对象的域名;
  • String getHostAddress():获取InetAddress对象的IP地址;
  • getLocalHost():获得一个InetAddress对象,该对象含有本地机的域名和IP地址。

DatagramPacket类

这个类代表了一个数据包,这个数据包被DatagramSocket的实例发送和接受。它除了包含需要发送和接受的数据外,还包含了发送和接受主机的IP地址等信息。
public byte[] getData():获取存放在数据报中的数据。
public int getLength():获取数据的长度。
public InetAddress getAddress():获取数据报中的IP地址。
public int getPort():获取数据报中的端口号。
public void setData(byte []buf):设置数据报中的内容为buf所存储的内容。

DatagramSocket类

这个类实现了一个用于发送和接受DatagramPacket的Socket,它的对象可以用于发送和接受包的任何一端。就是说它既可以用来发送包,也可以用来接受包。

关于这三个类的使用,可以总结位一下简单的四步:

<span style="font-family:SimSun;font-size:14px;">       //1、创建Socket用于UDP数据传送。  DatagramSocket socket = new DatagramSocket();  //2、创建数据包,注意,数据包包含了目的主机的ip地址  byte[] buf = "haha".getBytes();  DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 8888);  //3、发送  socket.send(packet);  //4、关闭socket.close();  </span>

接受与之类似

<span style="font-family:SimSun;font-size:14px;">        //1、创建Socket;  DatagramSocket socket = new DatagramSocket(8888);  //2、创建数据包,用于接收内容。  byte[] buf = new byte[1024];  DatagramPacket packet = new DatagramPacket(buf, buf.length);  //3、接收数据          socket.receive(packet);  System.out.println(packet.getAddress().getHostAddress()+":"+packet.getPort());   System.out.println(new String(packet.getData(), 0, packet.getLength()));  //4、关闭连接。  socket.close(); </span>

这两端程序没有做异常的处理,加上异常处理就可以工作了。

java编程

通过以上尝试,应该有信心写一个简单的测试程序,用于WOL了,写法很简单,主要需要严格按照魔术包的格式构造一个数据包,然后把这个数据包发送使用广播的方式发送出去。

下面是java的WOL代码,很简单,不多说了:

<span style="font-family:SimSun;font-size:14px;">import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;public class WakeOnLan {public static final int PORT = 7778;    public static void main(String[] args) {if (args.length != 2) {System.out.println("Usage: java WakeOnLan <broadcast-ip> <mac-address>");System.out.println("Example: java WakeOnLan 192.168.0.255 00:0D:61:08:22:4A");System.out.println("Example: java WakeOnLan 192.168.0.255 00-0D-61-08-22-4A");System.exit(1);}String ipStr = args[0];String macStr = args[1];try {byte[] macBytes = getMacBytes(macStr);byte[] bytes = new byte[6 + 16 * macBytes.length];//写入连续6个FFfor (int i = 0; i < 6; i++) {bytes[i] = (byte) 0xff;}//写入mac地址16次for (int i = 6; i < bytes.length; i += macBytes.length) {System.arraycopy(macBytes, 0, bytes, i, macBytes.length);}InetAddress address = InetAddress.getByName(ipStr);DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, PORT);DatagramSocket socket = new DatagramSocket();socket.send(packet);socket.close();StringBuilder sb = new StringBuilder();for(int i = 0;i<bytes.length;i++){sb.append(String.valueOf(Integer.valueOf(bytes[i])));}System.out.println("Wake-on-LAN packet sent:  "+sb);}catch (Exception e) {System.out.println("Failed to send Wake-on-LAN packet: + e");System.exit(1);}}private static byte[] getMacBytes(String macStr) throws IllegalArgumentException {byte[] bytes = new byte[6];String[] hex = macStr.split("(\\:|\\-)");if (hex.length != 6) {throw new IllegalArgumentException("Invalid MAC address.");}try {for (int i = 0; i < 6; i++) {bytes[i] = (byte) Integer.parseInt(hex[i], 16);}}catch (NumberFormatException e) {throw new IllegalArgumentException("Invalid hex digit in MAC address.");}return bytes;}}
</span>

用法举例:

java WakeOnLan 192.168.0.255   00-00-A0-00-E0-FF

android代码

先看下界面效果图:

布局文件:

<span style="font-family:SimSun;font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.konka.wakeonlan.MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Wake On Lan" /><EditTextandroid:id="@+id/ip"android:text="192.168.0.255"android:layout_width="match_parent"android:layout_height="wrap_content" /><EditTextandroid:id="@+id/mac_addr"android:text="00-00-A0-00-E0-FF"android:layout_width="match_parent"android:layout_height="wrap_content" /><Buttonandroid:id="@+id/wake_button"android:text="wake"android:layout_gravity="right"android:background="@color/colorAccent"android:layout_width="wrap_content"android:layout_height="wrap_content" />
</LinearLayout></span>

Activity:

public class MainActivity extends AppCompatActivity {EditText ip = null;EditText macAddr = null;Button button = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button = (Button) findViewById(R.id.wake_button);ip = (EditText) findViewById(R.id.ip);macAddr = (EditText) findViewById(R.id.mac_addr);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String lip = ip.getText().toString();String lmacAddr = macAddr.getText().toString();if (lip == null){ip.setText("please input ip!");}Log.d("hello",lip);if(lmacAddr == null){macAddr.setText("please input mac!");}Log.d("hello",lmacAddr);if(lip != null && lmacAddr != null){new WakeThread(lip,lmacAddr).start();}Toast.makeText(MainActivity.this,"send wake package",Toast.LENGTH_SHORT);}});}
}

发送魔术包线程:

public class WakeThread extends Thread{String ip = null;String macAddr = null;public WakeThread(String ip,String macAddr){this.ip = ip;this.macAddr = macAddr;}@Overridepublic void run() {super.run();wakeOnLan(ip,macAddr);}public void wakeOnLan(String ip,String macAddr){DatagramSocket datagramSocket = null;try {byte[] mac = getMacBytes(macAddr);byte[] magic = new byte[6+16*mac.length];//1.写入6个FFfor (int i=0;i<6;i++){magic[i] = (byte)0xff;}//2.写入16次mac地址for(int i=6;i<magic.length; i += mac.length){System.arraycopy(mac,0,magic,i,mac.length);}datagramSocket = new DatagramSocket();DatagramPacket datagramPacket = new DatagramPacket(magic,magic.length, InetAddress.getByName(ip),8888);datagramSocket.send(datagramPacket);} catch (SocketException e) {e.printStackTrace();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if(datagramSocket != null)datagramSocket.close();}}private byte[] getMacBytes(String macStr) throws IllegalArgumentException {byte[] bytes = new byte[6];String[] hex = macStr.split("(\\:|\\-)");if (hex.length != 6) {throw new IllegalArgumentException("Invalid MAC address.");}try {for (int i = 0; i < 6; i++) {bytes[i] = (byte) Integer.parseInt(hex[i], 16);}}catch (NumberFormatException e) {throw new IllegalArgumentException("Invalid hex digit in MAC address.");}return bytes;}
}

注意1:不要忘记添加网络访问权限:

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

注意2:一定要设置要唤醒的主机WOL使能。这个具体的设备不一样,大家自行百度。
注意3:要唤醒设备的网络一定要接有线网连接。无线网就不行,至于为什么就不深究了。

在Android模拟器和手机中测试,都能成功唤醒电视。

Android实现wake-on-lan相关推荐

  1. WOL wake on lan 功能 nodejs android kotlin实现

    有些机器支持WOL功能,可以远程唤醒机器, 几乎所有品牌的硬件都支持WOL,由于安全原因,可能在软件上默认WOL处于关闭状态 原理 WOL(Wake on Lan),即局域网唤醒,从根本上来说是硬件设 ...

  2. 无线wifi如何远程唤醒?wake on lan网络唤醒及远程控制踩过的坑!

    相信好多人都有远程唤醒自家电脑的这个需求,我也因各种原因折腾了好久-直到现在,也算是没那么折腾了,在这里不说配置细节,只说说远程开机唤醒的特定要求.遇到问题.解决方案,让能有幸看到人同学少走点弯路! ...

  3. 设置网络唤醒电脑(WAKE ON LAN,WOL)

    网络唤醒,就是通过有线网卡的形式,向电脑发送魔术包(Magic Packet),让电脑自动开机. 在支持ErP省电技术的主板下,必须要关闭ErP选项. 进入bios中设置,让主板支持通过(由PCI-E ...

  4. wake on lan 远程唤醒/远程开机中的所有设置细节(arp静态绑定解决长时间关机无法唤醒)

    远程开机这个功能实在屌爆了,工作中会经常遇到需要远程开机的情景,比如说,晚上在家里,突然接到领导的电话需要改东西,然而家里的电脑又没有工作环境,各种工具软件都没有安装,这时如果往公司跑一趟真是麻烦,或 ...

  5. 在Linux下通过Wake On LAN实现网络唤醒远程开机

    我们经常有这样的场景或需求,人在外面,需要将家里的机器或公司的机器开启,进行远程控制操作. 有几种方式可以实现远程开机,一是通过主板的来电自启动,通过智能开关远程开机.还有一种方式就是可以通过一台已经 ...

  6. 主板开启网络唤醒(Wake on lan)

    记录几个主板开启网络唤醒的链接: 华硕主板实现Wake on lan 网络唤醒的种种细节: https://blog.csdn.net/weixin_44607961/article/details/ ...

  7. 总结几点 Wake On Lan (WOL) 失败的原因

    正文 在我想使用 Wake On Lan(后文皆用 WOL 代替)这项技术远程开机时,总是失败,在查阅各种资料后成功使用上了 WOL,下面总结几点导致失败的原因. 1,发送 Magic Packet( ...

  8. 使用Wake On Lan远程唤醒

    使用Wake On Lan远程唤醒 客厅里的那台htpc,在无下片任务的时候,大部分时间里都在白白浪费电.主板是支持wake on lan的,把它弄成可以远程控制会比较经济. 首先要设置bios,将电 ...

  9. 基于OpenWrt的Wol(wake on lan)远程唤醒

    原理:向支持唤醒的网卡,发送特定格式的数据帧,从而启动计算机.正想起名字Wol,wake on lan 一样,是通过lan口发送的数据.所以设备要通过网线和路由器相连. 功能比较好实现,只有两个点: ...

  10. NAS折腾笔记之Wake On LAN和远程管理

    最近对华硕的印象很差,几年前组的台式机,为了带大显卡和多显卡,买了全尺寸的大板z170 pro gamming.结果这板子没发挥啥作业就吃灰了.最近把他翻出了玩truenas,结果wake on la ...

最新文章

  1. Java为什么会有默认的背景色_java – 为什么我的背景颜色不会在JFrame中...
  2. Android 自定义长按响应时间
  3. php指定键名排序,php二维数组指定其键名对其排序的方法
  4. java中主线程首先执行_java经典面试题:子线程先运行30次主线程,主线程40次,如此循环50次?...
  5. [免费网络研讨会] Java 11的第一印象
  6. LeetCode 460. LFU缓存(哈希双链表)
  7. 双非毕业生,如何入职大厂
  8. mysql读写分离的含义_MySQL 主从复制与读写分离概念及架构分析
  9. python生成指定长度的列表_如何在python中创建固定大小列表?
  10. 【书评:Oracle查询优化改写】第三章
  11. 中国人口增长的数学模型(for数学建模)
  12. TF卡和SD卡的区别
  13. 游戏逆向 修改植物大战僵尸阳光值
  14. Oracle官文,明确20c不能用于生产环境
  15. 以“降”为进,阿里云“被集成”
  16. nginx配置访问白名单
  17. 批处理中的for详解
  18. 触摸屏显示接口设计-用于便携式热像仪的OMAP双核处理器
  19. C#:实现ADBlock plus(网页广告监测)算法(附完整源码)
  20. 使用DataGrip编写SQL语句时出现此报错:“ Incorrect string value: ‘\xE7\x94\xB7‘ for column ‘xx‘ at row x”

热门文章

  1. php 防止僵尸程序,PHP多进程编程之僵尸进程问题
  2. java数据库编程中查询结果的表格式输出_Java数据库编程中查询结果的表格式输出...
  3. c语言中 队列用法,c中queue的用法
  4. 解决CSV文件打开乱码的问题
  5. 使用Matplotlib绘图
  6. YOLOv5安全帽检测
  7. BPR贝叶斯个性化排序算法
  8. MySQL表结构导出
  9. 荣耀70和opporeno8哪个值得买 两者配置对比
  10. C语言如何生成随机数——随机数原理分析