近日为了满足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.log4j.PropertyConfigurator;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.mail.javamail.JavaMailSender;
import com.eehome.app.mail.IMailConstant;
import com.eehome.app.mail.model.IpNotifyMessage;
import com.eehome.app.mail.utils.RouteIpUtils;
/**
* 邮件提醒任务
* @author wensong
* 2010-9-5 下午11:12:17
*/
public class NotifyEmailSendTask implements Runnable {
private String[] toMails;
private Log logger = LogFactory.getLog(this.getClass());
private static String ip = "192.168.1.110";
static {
PropertyConfigurator.configure(IMailConstant.LOG4J_FILE_PATH);
}
private static BeanFactory factory = new ClassPathXmlApplicationContext(
"application-context.xml");
public NotifyEmailSendTask(String[] toMails) {
this.toMails = toMails;
}
public void run() {
String routerIp = null;
try {
routerIp = RouteIpUtils.getInstance().getRouteIp();
} catch (IOException e1) {
logger.warn("连接路由中断,或者路由连接异常:" + e1);
}
try {
if (routerIp != null&&!routerIp.equals("0.0.0.0")) {
if (!routerIp.equals(ip)) {
if (!ip.equals("192.168.1.110"))
logger.info("路由IP发生变化,执行发送邮件任务");
StringBuffer context = new StringBuffer().append(
"今日Host:\n").append("eehome.com ")
.append(routerIp);
if (!ip.equals("192.168.1.110")) {
context = new StringBuffer().append("Host变化如下:\n")
.append("eehome.com ").append(routerIp);
}
// 构造邮件消息对象
IpNotifyMessage message = new IpNotifyMessage(toMails,
context.toString());
// 发邮件
JavaMailSender mailSender = (JavaMailSender) factory
.getBean("javaMailSender");
logger.info("发送邮件,发送邮箱为:" + Arrays.toString(toMails));
mailSender.send(message);
ip = routerIp;
} else {
logger.debug("上次记录的IP为:" + ip + ", 最新路由IP为:" + routerIp
+ " 轮询结果将不发送邮件");
}
}
} catch (Exception e) {
logger.warn("发送邮件异常:" + e);
}
}
}
package com.eehome.app.mail.task;
import java.util.concurrent.TimeUnit;
import com.eehome.app.mail.IMailConstant;
import com.eehome.app.mail.utils.EmailsProvider;
import com.eehome.core.task.EeHomeScheduledExecutor;
/**
* 邮件任务调度,采用轮询的方式来检查路由IP是否发生改变,如果改变发送邮件
*
* @author wensong 2010-9-4 下午03:34:58
*/
public class IpNotifyEmailSchedule {
public static void main(String[] args) {
String[] mails = EmailsProvider.getInstance().getEmailArrays();
EeHomeScheduledExecutor.getScheduledExecutor().scheduleWithFixedDelay(
new NotifyEmailSendTask(mails), 0, IMailConstant.POLLING_TIME,
TimeUnit.MILLISECONDS);
}
}
package com.eehome.app.mail.model;
import java.util.Date;
import org.springframework.mail.SimpleMailMessage;
import com.eehome.app.mail.IMailConstant;
import com.eehome.app.mail.utils.DateUtils;
public class IpNotifyMessage extends SimpleMailMessage {
private static final long serialVersionUID = -3236307360187426650L;
public IpNotifyMessage(String toMail, String toText) {
// 设置邮件标题:提醒邮件标题前缀+当前时间
setSubject(IMailConstant.NOTIFY_EMAIL_MESSAGE_PRE_TITLE
+ DateUtils.getTimeNow());
setFrom(IMailConstant.NOTIFY_EMAIL_MESSAGE_FROM);
setSentDate(new Date());
setTo(toMail);
setText(toText);
}
public IpNotifyMessage(String[] toMails,String toText){
// 设置邮件标题:提醒邮件标题前缀+当前时间
setSubject(IMailConstant.NOTIFY_EMAIL_MESSAGE_PRE_TITLE
+ DateUtils.getTimeNow());
setFrom(IMailConstant.NOTIFY_EMAIL_MESSAGE_FROM);
setSentDate(new Date());
setTo(toMails);
setText(toText);
}
}
package com.eehome.app.mail.exception;
public class FileIsNotExistException extends Exception {
/**
* 文件不存在异常
*/
private static final long serialVersionUID = -2545287258814097123L;
public FileIsNotExistException() {
super();
}
public FileIsNotExistException(String message, Throwable cause) {
super(message, cause);
}
public FileIsNotExistException(String message) {
super(message);
}
public FileIsNotExistException(Throwable cause) {
super(cause);
}
}
package com.eehome.app.mail.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.PropertyConfigurator;
import com.eehome.app.mail.IMailConstant;
public class EmailsProvider {
private final static EmailsProvider provider = new EmailsProvider();
private Log logger = LogFactory.getLog(this.getClass());
static {
PropertyConfigurator.configure(IMailConstant.LOG4J_FILE_PATH);
}
private EmailsProvider() {
}
public static EmailsProvider getInstance() {
return provider;
}
/**
* 获得Email数组
*
* @return
*/
public String[] getEmailArrays() {
StringBuilder sb = getEmailStrBuilder();
if (sb != null) {
List<String> mailArrays = getEmails(sb);
return (String[]) mailArrays.toArray(new String[mailArrays.size()]);
} else {
return null;
}
}
/**
* 从指定email配置中获取email
*
* @return
*/
private StringBuilder getEmailStrBuilder() {
File file = new File(IMailConstant.EMAIL_FILE_PATH);
InputStream ins = null;
StringBuilder stringBuilder = new StringBuilder();
try {
ins = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(
ins));
String str;
while ((str = reader.readLine()) != null) {
stringBuilder.append(str).append(",");
}
return stringBuilder;
} catch (FileNotFoundException e) {
logger.info(file.getPath() + "文件不存在");
return null;
} catch (IOException e) {
logger.info("文件操作异常:" + e);
return null;
} finally {
try {
ins.close();
} catch (IOException e) {
logger.info("文件关闭异常:" + e);
return null;
}
}
}
/**
* 通过正则匹配字符
* @param stringBuilder
* @return
*/
private List<String> getEmails(StringBuilder stringBuilder) {
List<String> mails = new ArrayList<String>();
// 创建正则表达式
Pattern p = Pattern.compile(IMailConstant.EMAIL_REG);
Matcher m = p.matcher(stringBuilder);
if (logger.isDebugEnabled()) {
logger.debug("文件读取的字符串stringBuilder:" + stringBuilder);
}
// 找到匹配的字符串
while (m.find()) {
mails.add(m.group());
}
return mails;
}
}
package com.eehome.app.mail.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtils {
public static final SimpleDateFormat sdf = new SimpleDateFormat(
"yyyyMMddHHmmss");
/**
* 获得当前时间组成的字符串,格式为yyyyMMddHHmmss
* @return
*/
public static String getTimeNow() {
return sdf.format(new Date());
}
}
package com.eehome.app.mail.exception;
public class FileIsNotExistException extends Exception {
/**
* 文件不存在异常
*/
private static final long serialVersionUID = -2545287258814097123L;
public FileIsNotExistException() {
super();
}
public FileIsNotExistException(String message, Throwable cause) {
super(message, cause);
}
public FileIsNotExistException(String message) {
super(message);
}
public FileIsNotExistException(Throwable cause) {
super(cause);
}
}
接着为了写了一个shell脚本,把它作为一个后台执行的脚本,放到rc.local下,让其开机启动,这样IP邮件提醒的程序大功告成,呵呵。
分享到:
相关推荐
8. **代码实践**:实际的Java代码会包含上述步骤的实现,包括初始化网络管理对象,检查权限,获取IP信息,转换IP整数值为字符串,以及处理异常等。 通过这样的demo,开发者可以学习如何在Android环境中动态获取设备...
《JavaSwing局域网斗地主:技术详解与实现剖析》 在计算机科学领域,游戏开发是一项富有挑战性的任务,尤其是局域网内的多人在线游戏。本项目“JavaSwing局域网斗地主”就是一个这样的实例,它充分利用了Java的特性...
在Java编程中,判断一个IP地址是内网IP(私有IP)还是公网IP(全局IP)是一项常见的任务,尤其在网络编程和服务器配置中。内网IP通常用于局域网内部通信,而公网IP则是互联网上的唯一标识。下面将详细探讨如何实现这...
不过,由于描述中提到“如果有外网的服务器IP,理论上支持外网”,这意味着该软件可能已经具备了这样的功能,但是否可行还需要用户自行测试。 总的来说,这个JAVA编写的局域网群聊天软件是一个典型的JAVA网络编程...
获取外网IP地址的原理是通过访问外网网站,从网站返回的数据中解析本地的IP地址。下面是相应的源码实例: ```java public static String getOutNetIP() { String ipAddress = ""; try { String address = ...
在Java编程中,判断一个IP地址是内网IP(Private IP)还是公网IP(Public IP)通常涉及到网络通信和TCP/IP协议的理解。TCP/IP协议为了提高网络效率和安全性,将一部分IP地址范围预留给了内部网络使用,这些IP地址...
- **IP查询工具**允许用户获取其设备的当前IP地址,包括内网IP和外网IP。这通常通过向特定的网站或应用发送请求来实现,这些网站或应用返回用户的IP信息。 5. 网络诊断: - 这种工具不仅可以显示IP地址,还可以...
在IT领域,局域网监控程序是一种...总的来说,这个Java局域网监控程序是一个强大的工具,能够帮助IT专业人员有效地管理和保护他们的网络环境。通过持续的维护和升级,它可以在不断变化的网络安全环境中发挥重要作用。
在IT领域,了解和获取本机IP地址以及外网IP地址是常见的需求,尤其是在网络编程、服务器配置或者网络诊断中。下面将详细解释这两个概念及其获取方法。 首先,我们要理解什么是"本机IP"和"外网IP"。 1. 本机IP...
在Android开发中,有时我们需要获取连接到手机热点设备的IP地址,这在设备间通信、网络诊断或构建本地网络服务时特别有用。本教程将详细解释如何实现这一功能,主要涉及"IP地址获取"和"手机AP"这两个关键知识点。 ...
java调用海康威视sdk摄像头推流到阿里云,并通过ckplayer进行网页播放
【Java局域网聊天系统】是一种基于Java编程语言开发的通信应用,主要设计用于局域网环境中的用户间即时通讯。这个系统的核心特点是通过输入对方的IP地址来建立连接,从而实现两人之间的文本聊天功能。在理解这个系统...
综上所述,这份局域网聊天室课程设计不仅涵盖了理论知识的学习,更重要的是通过实践让学生掌握了网络编程的基础技能,尤其是在Java环境下实现TCP/IP协议的具体方法。通过这样的实践项目,学生不仅能深入了解网络通信...
其次,介绍TCP/IP点对点协议技术,C/S架构和SOCKET网络编程技术;再次,对当前局域网文件传输进行需求分析并提出解决方案;然后,根据解决方案对系统进行设计;最后,对工作计划统计以及分析系统进行测试并得到测试...
### JAVA源码JAVA基于局域网的聊天室系统(源代码+论文) #### 知识点一:局域网聊天室系统的实现原理 局域网(Local Area Network, LAN)是一种在有限地理区域内连接计算机和其他网络设备的技术。局域网聊天室系统...
在VMware中配置Linux系统以实现局域网和外网访问是每个Linux用户的基本技能,尤其是对于初学者来说,这一步至关重要。以下是一份详细的步骤指南,帮助您完成这一过程。 首先,确保您的VMware虚拟机已经安装了Linux...
"Android获取实时连接热点的设备IP" Android获取实时连接热点的设备IP是指在Android系统中获取当前热点连接的设备IP地址的相关技术。主要涉及到Android系统中获取Wifi热点设备的Ip地址的代码实现。 知识点一:/...
2. **IP地址检测**:程序需要能够获取到邮件主机的内网IP和外网IP。内网IP通常是在局域网内的设备间通信时使用的,可以通过执行`ifconfig`(Linux)或`ipconfig`(Windows)命令获取。外网IP则是互联网上识别邮件...
4. **处理局域网和外网IP**: - **局域网IP**:在本地测试时,如果Flex应用与Web服务在同一网络环境(例如,都在开发者的局域网内),返回的IP可能是局域网内的IP地址,如192.168.x.x。 - **外网IP**:当应用通过...
在局域网监控中,通常会使用编程语言(如C#、Python或Java)编写源程序,通过发送远程桌面请求或者利用VNC(Virtual Network Computing)协议,实现在不被察觉的情况下获取目标计算机的屏幕画面。 三、实现方式 1....