基于Java实现计算机远程唤醒(WOL)功能

网络唤醒,即WOL。简单来讲就是电脑在关闭状态,可以通过网络发送特殊数据包给网卡,网卡收到指定包后,开启计算机。WOL要求有硬件支持该功能,目前市场上主流的以太网卡都支持WOL功能,而无线网卡查找了许多没找到支持该功能的无线网卡。

我在家已经成功实现了网络唤醒功能,可如果我在公司需要操作家里电脑,而网络唤醒是基于局域网的,则无法办到。于是我想到了通过访问家里路由器的网络IP地址实现,但是家里的网络IP地址是变化的,每次重启路由器都会更换,自己总不能每次重启路由器都要记一遍网络IP地址吧。

为了解决这个问题,我想到了花生壳。家里的路由是TP-LINK,集成了花生壳的DDNS功能,使用后发现小区宽带经过N重路由,花生壳获取到的网络IP地址根本不正确,纠结。几经波折发现可以为花生壳设置A记录,指定域名的IP,同时花生壳也提供了修改A记录的接口,于是我萌生了一个想法:每当路由器重启时,获取路由器网络IP地址,然后通过花生壳接口修改域名A记录,这样外网就可以通过域名发送网络唤醒包,实现远程开机,想法是多么的高大上啊,但过程很艰辛!

废话太多了,先让我们了解一下花生壳的开放接口吧,我使用的是。

地址:http://open.oray.com/wiki/doku.php

看文档我们了解到,主要分DDNS协议和HTTP协议两种。DDNS协议需要保持心跳包,即每个一段时间发送相应数据给花生壳,显然不是我们想要的,所以我选择HTTP协议。

官网HTTP协议如下:

当客户端发现IP地址变化或是用户修改设置时,客户端应该进行更新。

所有的更新都基本于标准的HTTP请求发送。

服务器会传回一个返回代码,客户端需要解析。

HTTP请求

主机名:ddns.oray.com

HTTP端口:80

HTTPS 端口:443

请求支持HTTP和基于SSL的HTTPS协议(HTTPS需要付费用户才能使用)

所有客户端必须发送一个完整的User-Agent文件头,用于区分不同的设备,空值或非法参数将导致请求失败。

例子

1.使用URL验证

适用于浏览器或应用程序(fetch, curl, lwp-request),可以在URL中包含验证信息。

http://username:[email protected]/ph/update?hostname=yourhostname&myip=ipaddress

2.原始HTTP GET请求

实际的HTTP请求,类似下面的代码。

其中 base-64-authorization 请使用 Base64 加密 username:password 后的字符替换。

GET /ph/update?hostname=yourhostname&myip=ipaddress HTTP/1.0

Host: ddns.oray.com

Authorization: Basic base-64-authorization

User-Agent: Oray

请注意必须使用GET请求,POST是不被允许的。

更新参数

目前仅允许提交以下参数

参数 说明

hostname 需要更新的域名,此域名必须是开通花生壳服务。多个域名使用,分隔,默认为空,则更新护照下所有激活的域名。例:hostname=test.oray.com,customtest.oray.com

myip 需要更新的IP地址,可以不填。如果不指定,则由服务器获取到的IP地址为准。

起初看这个文档我是云里雾里的,经过几番折腾终于弄明白了。

1.以GET方式发送HTTP请求到http://ddns.oray.com/ph/update?hostname=yourhostname&myip=ipaddress

2.hostname值为要修改的域名

3.myip值为要修改的IP地址,即家中路由器的公网IP地址

4.请求头User-Agent为浏览器型号

5.请求头Authorization为 花生壳登录名:密码 用BASE64方式加密内容

比如账号为:1234;密码为12345,即1234:12345的BASE64加密结果为:MTIzNDoxMjM0NQ==

后面的问题就是如何获取公网IP了,发现http://www.ip138.com/这个网站获取的公网IP地址和路由器是一致的,再看http://www.ip138.com/其实是通过http://1111.ip138.com/ic.as接口GET方式获取的,那么只需要读取http://1111.ip138.com/ic.asp的IP地址就可以了。

package smile.heyi.html;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;

/**
 * 获取公网IP地址
 * */
public class GetInternetIP {
	private final static String url = "http://1111.ip138.com/ic.asp";

	public static String getIP(){
		String ip = "";
		String html = getHTML();
		int start = html.indexOf("[")+1;
		int end = html.indexOf("]");
		//截取IP地址字符串
		ip = html.substring(start, end);
		return ip;
	}

	private static String getHTML(){
		String s = "";
		try {
			HttpURLConnection conn = (HttpURLConnection) (new URL(url).openConnection());
			conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 5.1; rv:35.0) Gecko/20100101 Firefox/35.0");
			conn.setRequestMethod("GET");

			BufferedReader bf = new BufferedReader(new InputStreamReader(conn.getInputStream(),"GBK"));
			String tmp = "";

			while((tmp = bf.readLine()) != null){
				s += tmp+"\r\n";
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return s;
	}
}

下面在调用花生壳的接口

package smile.heyi.html;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import smile.heyi.util.Base64;

/**
 * 通过花生壳接口,修改域名A记录
 * */
public class ChangeDDNS {
	private String url = "http://ddns.oray.com/ph/update";
	private String loginName = "";
	private String password = "";

	public ChangeDDNS(String name, String pw){
		this.loginName = name;
		this.password = pw;
	}

	public String change(String domainName, String ip){
		String s = "";

		url += "?hostname="+domainName+"&myip="+ip;
		try {
			HttpURLConnection conn = (HttpURLConnection) (new URL(url).openConnection());
			conn.setRequestProperty("Host", "ddns.oray.com");
			//模拟以FireFox浏览器身份访问
			conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 5.1; rv:35.0) Gecko/20100101 Firefox/35.0");
			//以 账号:密码 的BASE64加密结果身份登录
			conn.setRequestProperty("Authorization", "Basic "+Base64.getBASE64(loginName+":"+password));
			conn.setRequestProperty("Referrer", url);

			BufferedReader bf = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String tmp = "";
			while((tmp = bf.readLine()) != null){
				s += tmp;
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return s;
	}

}

剩下的就是BASE64加密登录信息

说明一下:网上看了一下算法,太复杂没懂,就从网上抄了一份。这份使用的sun.misc.BASE64Decoder和sun.misc.BASE64Encoder两个包,但是Eclipse会找不到,需要工程中删除JRE System Library然后重新添加才可以,究其原因貌似是因为这两个包是sun员工内部自己用的并没有对外发布(看名称就会觉得怪不是以java开头的),并不保证没问题,所以还是希望高手自己写吧。

package smile.heyi.util;

import java.io.IOException;
import sun.misc.BASE64Decoder;     
import sun.misc.BASE64Encoder;

/**
 * Base64加解密
 * */
public class Base64 {
	public static String getBASE64(String s){
		return (new BASE64Encoder()).encode(s.getBytes());
	}

	public static String deCodeBASE64(String key) throws IOException{
		byte[] b = (new BASE64Decoder()).decodeBuffer(key);
		return new String(b);
	}
}

最后的问题,就是怎么称才能在路由器重启的时候,执行这些操作了。

我们不能监测到路由器是否重启,但是可以监测到计算机网卡状态。每次路由器重启(开机状态下)网卡都会失去Internet连接然会回复Internet连接。那么我们可以做计划任务,每当网卡发生连接事件的时候,延迟10分钟左右执行以上的Java代码,延迟是为了防止网络连接未回复就去获取网络IP地址。

时间: 2024-10-05 13:20:21

基于Java实现计算机远程唤醒(WOL)功能的相关文章

Java编程实现获取本机IP和计算机名的功能

import java.net.InetAddress; import java.net.UnknownHostException; public class Test { public static void main(String[] args) { try { InetAddress inetAddress = InetAddress.getLocalHost(); System.out.println("本机IP:" + inetAddress.getHostAddress()

基于Java的Jess功能函数扩展方法

Jess是Java expert system shell的缩写,是Java平台上的规则引擎,它是CLIPS程序设计语言的超集,是完全使用Java语言编写一种用于开发专家系统的语言.对于基于规则的推理,特别是针对逻辑条件的推理,Jess是已知规则引擎中最快的.它以增强型Rete算法为基础,支持前向推理,也支持后向推理,具有直接对Java对象进行推理,支持对工作存储区的查询访问等特点[1-2]. Jess语言本身提供了很多功能强大的函数供专家系统开发者调用,但这些函数不可能囊括一切功能和运算,若仅

基于java实现的简单网页日历功能,有兴趣得可以把它转换到前端实现

之前做项目的时候,因为要用到不同日期显示不同的内容,就自己做了一个日期的显示和选择功能,今天抽空把以前的代码理了一下,顺便就把之前做的日期功能给拿出来回顾一下,大家可以提点意见,帮忙完善下设计.先上一张完成后的显示效果,本人是后端程序员,对于前端的一些效果不是很熟悉,画面不好请见谅.. 下面切入正题: 我设计的日历表是11*3的显示,加上上一个月和下一个月的选项,对于大月的月份刚好足够,但小月和二月就会有空格.为了方便我在页面上展现日历,我将上一月.下一月.空字符和日期一起封装在了list集合中

Lucene:基于Java的全文检索引擎简介 (zhuan)

http://www.chedong.com/tech/lucene.html ********************************************** Lucene是一个基于Java的全文索引工具包. 基于Java的全文索引引擎Lucene简介:关于作者和Lucene的历史 全文检索的实现:Luene全文索引和数据库索引的比较 中文切分词机制简介:基于词库和自动切分词算法的比较 具体的安装和使用简介:系统结构介绍和演示 Hacking Lucene:简化的查询分析器,删除的

Lucene:基于Java的全文检索引擎简介

Lucene是一个基于Java的全文索引工具包. 基于Java的全文索引引擎Lucene简介:关于作者和Lucene的历史 全文检索的实现:Luene全文索引和数据库索引的比较 中文切分词机制简介:基于词库和自动切分词算法的比较 具体的安装和使用简介:系统结构介绍和演示 Hacking Lucene:简化的查询分析器,删除的实现,定制的排序,应用接口的扩展 从Lucene我们还可以学到什么 另外,如果是在选择全文引擎,现在也许是试试 Sphinx的时候了:相比Lucene速度更快, 有中文分词的

基于java的简单Socket编程

1TCP协议与UDP协议     1.1 TCP               TCP是(Tranfer Control Protocol)的简称,是一种面向连接的保证可靠传输的协议.通过TCP协议传输,得到的是一个顺序的无差错的数据流.发送方和接收方的成对的两个socket之间必须建立连接,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作. TCP的

基于Java Web的猜歌游戏设计与实现

获取项目源文件,技术交流与指导联系Q:1225467431 摘   要 随着社会的不断发展,越来越多的人面临的压力越来越大,人们渴望随时随地都能放松自我.然而游戏正成为人们释放压力,放松自己最行之有效的娱乐方式之一.而基于Java Web的猜歌游戏以其界面美观,操作简单,对硬件要求低等优点将会备受大家的青睐.系统通过数据库对用户基本信息和歌曲信息进行统一管理,借助经典的框架Servlet对数据进行处理,又选择了前端一些功能强大的插件对数据进行展示,将猜歌与游戏很好的结合起来,意在给用户创造了一个

基于Java Web SSH框架的网上书店

获取项目源文件,技术交流与指导联系Q:1225467431 摘   要 随着互联网技术的发展,网上购物越来越流行,而网上书店更是逐渐受到越来越多的人关注,不用涉及交通.不用到书店翻阅.即可看到全国各地的书籍价格.更加全面地搜索自己喜欢的书籍.需要的书籍.通过网络销售系统的平台,商家将拥有更大的市场,能更加及时快速地得到用户对于商品的反响,可以随时调整销售策略,提高商家的市场竞争力.对于消费者也提供了方便,消费者可以不受时间和地域的限制进行购物,并且可以获取更多信息.. 本文阐述了如何构建基于B/

基于Java Web的新闻发布系统设计与实现

获取项目源文件,技术交流与指导联系Q:1225467431 摘要:现如今快速发展的互联网,已成为新兴的媒体发布形式,逐步影响到传统媒体行业的发展.与传统的信息传播媒体如电视.广播.报纸等相比,电脑.智能手机等终端因其传递信息方便.快捷,并满足人们对外界瞬息万变的信息的好奇心的特点,使得人们对网络新闻媒体越来越依赖.针对上述状况,推出了基于Java Web的新闻发布系统,在开发中基于My Eclipse平台,采用Tomcat 服务器,使用数据库My SQL.系统具有很好的人机界面,不仅实现了管理员