近日为了满足2个屋子里人的通信需要,需要将本地的外网IP告诉给另一个屋子里的人。以前都是在群里喊一句,我这里的IP是XXXX,有一天自己突发奇想,想通过程序来实现这个自动化通知的过程。于是自己给自己定了需求。
需求:基本目标实现开机将本地的路由WAN口IP通知对方。
思考:如果才能实现自动通知呢?
首先,要有一个公共的空间,可以作为通知的载体。
其次,需要传输机制把通知发出去。
经过思考,我想到了电子邮件,邮箱是每个人都有的,email是可以用程度发的。于是需求变成了通过发邮件的方式把最新获取到的IP发出来。解决的思路有 了,最大的问题是如何获取外网IP,开始尝试获取本地IP,这个显然是没用的,因为机器是在内网环境,获取到的只是内网IP,后来试图想通过获取外网 IP,比如访问一个XXX网站的形式来获取IP,这种网站还真不少,但是获取到的都是公网IP,学过网络的人都知道公网IP很少,往往只是在网络节点上的 IP,这种IP对我一个ADSL用户来说几乎就没任何意义。其实我需要的只是路由的WAN口IP。网上搜了一下,也没找到合适的。在几乎绝望的时候,我想
到了代理,我能不能通过访问路由器的方式来获取IP呢,我试图用telnet登陆路由,试图用路由命令来操作路由,结果和我想象的一样,家用路由毕竟不是 服务器级别的路由,根本没有对外提供的访问命令,只能通过web的方式来实现对路由的设置。自己再次陷入了绝望,后来我打开fireBug,试图找到IP 那个查看IP跳转的页面。结果被我找到了,http://192.168.1.1/userRpm/StatusRpm.htm,点开页面查看响应,传过 来的就是网页的部分信息。OK,这就是我想要的IP。我突然兴奋起来,但是这似乎还不够,因为每次登陆路由时要输入用户名和密码。网上搜搜,这个其实不
难,代理服务程序就那样写的。经过一晚上的思考和实践WAN口IP算是被我搞出来了。
- package com.eehome.app.mail.utils;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.net.Authenticator;
- import java.net.URL;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- import com.eehome.app.mail.IMailConstant;
- import com.eehome.app.mail.model.RouterPassAuth;
- /**
- * @author wensong
- * 2010-9-4 下午03:34:58
- */
- public class RouteIpUtils {
- private final static RouteIpUtils routeIpUtils = new RouteIpUtils();
- private RouteIpUtils() {
- }
- public static RouteIpUtils getInstance() {
- //验证器工具的实例进行注册
- Authenticator.setDefault(new RouterPassAuth());
- return routeIpUtils;
- }
- public String getRouteIp() throws IOException {
- StringBuffer wanPacket = getWanPacket();
- return getFirstIp(wanPacket);
- }
- /**
- * 获得路由Web中的状态页面上的数据
- *
- * @return
- * @throws IOException
- */
- private StringBuffer getWanPacket() throws IOException {
- URL url = new URL(IMailConstant.ROUTE_WEB_STATE);
- InputStream ins = null;
- try {
- ins = url.openConnection().getInputStream();
- BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
- String str;
- boolean flag = false;
- StringBuffer wanPacket = new StringBuffer();
- int num = 3;
- while ((str = reader.readLine()) != null && num > 0) {
- if (str.contains("var wanPara = new Array(")) {
- flag = true;
- }
- if (flag) {
- wanPacket.append(str);
- num--;
- }
- }
- return wanPacket;
- }finally{
- if(ins!=null){
- ins.close();
- }
- }
- }
- private String getFirstIp(StringBuffer wanPacket) {
- // 找出数据包中第一个匹配的IP,即为Ip
- Pattern p = Pattern.compile("\\d+\\.\\d+\\.\\d+\\.\\d+");
- Matcher m = p.matcher(wanPacket);
- if (m.find()) {
- return m.group();
- } else {
- return null;
- }
- }
- public static void main(String[] args) {
- try {
- System.out.println(RouteIpUtils.getInstance().getRouteIp());
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- package com.eehome.app.mail;
- public interface IMailConstant {
- /**
- * 发件人地址
- */
- public final static String NOTIFY_EMAIL_MESSAGE_FROM = "wensong1987@126.com";
- /**
- * 提醒邮件标题前缀
- */
- public final static String NOTIFY_EMAIL_MESSAGE_PRE_TITLE = "通知:服务器IP提醒————";
- /**
- * 路由用户名
- */
- public final static String ROUTE_USER = "admin";
- /**
- * 路由密码
- */
- public final static String ROUTE_PWD = "huang";
- /**
- * 路由Web记录状态的页面,里面包含了Wan口ip
- */
- public final static String ROUTE_WEB_STATE = "http://192.168.1.1:83/userRpm/StatusRpm.htm?Connect=连 接&wan=1";
- /**
- * 轮询时间 10分钟
- */
- public final static long POLLING_TIME = 10 * 60 * 1000;
- /**
- * email文件地址
- */
- public final static String EMAIL_FILE_PATH = "/root/mail/mail.txt";
- /**
- * log4j存放地址
- */
- public final static String LOG4J_FILE_PATH = "/root/mail/log/log4j.properties";
- /**
- * 匹配email的正则
- */
- public final static String EMAIL_REG = "[A-Za-z0-9](?:[0-9a-zA-Z_]?\\.?){4,24}@[0-9a-zA-Z_-]{1,59}\\.(?:[0-9a-zA-Z]\\.?[0-9a-zA-Z]?){2,3}";
- }
- package com.eehome.app.mail.model;
- import java.net.Authenticator;
- import java.net.PasswordAuthentication;
- import com.eehome.app.mail.IMailConstant;
- public class RouterPassAuth extends Authenticator {
- @Override
- public PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication(IMailConstant.ROUTE_USER,
- IMailConstant.ROUTE_PWD.toCharArray());
- }
- }
考虑到路由IP是动态IP,过一段时间就会变化,我给程序设计了一个轮询机制来检测IP,变化,用一个调度任务来定时获取IP,进行比较,再决定是否发送邮件。
- package com.eehome.app.mail.task;
- import java.io.IOException;
- import java.util.Arrays;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.apache