Android实现wake-on-lan
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代码
![](/assets/blank.gif)
布局文件:
<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相关推荐
- WOL wake on lan 功能 nodejs android kotlin实现
有些机器支持WOL功能,可以远程唤醒机器, 几乎所有品牌的硬件都支持WOL,由于安全原因,可能在软件上默认WOL处于关闭状态 原理 WOL(Wake on Lan),即局域网唤醒,从根本上来说是硬件设 ...
- 无线wifi如何远程唤醒?wake on lan网络唤醒及远程控制踩过的坑!
相信好多人都有远程唤醒自家电脑的这个需求,我也因各种原因折腾了好久-直到现在,也算是没那么折腾了,在这里不说配置细节,只说说远程开机唤醒的特定要求.遇到问题.解决方案,让能有幸看到人同学少走点弯路! ...
- 设置网络唤醒电脑(WAKE ON LAN,WOL)
网络唤醒,就是通过有线网卡的形式,向电脑发送魔术包(Magic Packet),让电脑自动开机. 在支持ErP省电技术的主板下,必须要关闭ErP选项. 进入bios中设置,让主板支持通过(由PCI-E ...
- wake on lan 远程唤醒/远程开机中的所有设置细节(arp静态绑定解决长时间关机无法唤醒)
远程开机这个功能实在屌爆了,工作中会经常遇到需要远程开机的情景,比如说,晚上在家里,突然接到领导的电话需要改东西,然而家里的电脑又没有工作环境,各种工具软件都没有安装,这时如果往公司跑一趟真是麻烦,或 ...
- 在Linux下通过Wake On LAN实现网络唤醒远程开机
我们经常有这样的场景或需求,人在外面,需要将家里的机器或公司的机器开启,进行远程控制操作. 有几种方式可以实现远程开机,一是通过主板的来电自启动,通过智能开关远程开机.还有一种方式就是可以通过一台已经 ...
- 主板开启网络唤醒(Wake on lan)
记录几个主板开启网络唤醒的链接: 华硕主板实现Wake on lan 网络唤醒的种种细节: https://blog.csdn.net/weixin_44607961/article/details/ ...
- 总结几点 Wake On Lan (WOL) 失败的原因
正文 在我想使用 Wake On Lan(后文皆用 WOL 代替)这项技术远程开机时,总是失败,在查阅各种资料后成功使用上了 WOL,下面总结几点导致失败的原因. 1,发送 Magic Packet( ...
- 使用Wake On Lan远程唤醒
使用Wake On Lan远程唤醒 客厅里的那台htpc,在无下片任务的时候,大部分时间里都在白白浪费电.主板是支持wake on lan的,把它弄成可以远程控制会比较经济. 首先要设置bios,将电 ...
- 基于OpenWrt的Wol(wake on lan)远程唤醒
原理:向支持唤醒的网卡,发送特定格式的数据帧,从而启动计算机.正想起名字Wol,wake on lan 一样,是通过lan口发送的数据.所以设备要通过网线和路由器相连. 功能比较好实现,只有两个点: ...
- NAS折腾笔记之Wake On LAN和远程管理
最近对华硕的印象很差,几年前组的台式机,为了带大显卡和多显卡,买了全尺寸的大板z170 pro gamming.结果这板子没发挥啥作业就吃灰了.最近把他翻出了玩truenas,结果wake on la ...
最新文章
- Java为什么会有默认的背景色_java – 为什么我的背景颜色不会在JFrame中...
- Android 自定义长按响应时间
- php指定键名排序,php二维数组指定其键名对其排序的方法
- java中主线程首先执行_java经典面试题:子线程先运行30次主线程,主线程40次,如此循环50次?...
- [免费网络研讨会] Java 11的第一印象
- LeetCode 460. LFU缓存(哈希双链表)
- 双非毕业生,如何入职大厂
- mysql读写分离的含义_MySQL 主从复制与读写分离概念及架构分析
- python生成指定长度的列表_如何在python中创建固定大小列表?
- 【书评:Oracle查询优化改写】第三章
- 中国人口增长的数学模型(for数学建模)
- TF卡和SD卡的区别
- 游戏逆向 修改植物大战僵尸阳光值
- Oracle官文,明确20c不能用于生产环境
- 以“降”为进,阿里云“被集成”
- nginx配置访问白名单
- 批处理中的for详解
- 触摸屏显示接口设计-用于便携式热像仪的OMAP双核处理器
- C#:实现ADBlock plus(网页广告监测)算法(附完整源码)
- 使用DataGrip编写SQL语句时出现此报错:“ Incorrect string value: ‘\xE7\x94\xB7‘ for column ‘xx‘ at row x”