`
wensong
  • 浏览: 127444 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java获取本地局域网的外网IP

阅读更多

      近日为了满足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邮件提醒的程序大功告成,呵呵。

 

 

6
1
分享到:
评论
3 楼 partners 2013-07-09  
这个需要用户、密码,有没办法不用账号密码
2 楼 gaowei52306 2012-09-09  
刚好可以借鉴一下。
1 楼 zhj_bbt 2012-01-19  
希望楼主能把源代码还有shell脚本发到附件上,嘿嘿!

相关推荐

    获取android设备的内网IP地址

    8. **代码实践**:实际的Java代码会包含上述步骤的实现,包括初始化网络管理对象,检查权限,获取IP信息,转换IP整数值为字符串,以及处理异常等。 通过这样的demo,开发者可以学习如何在Android环境中动态获取设备...

    JavaSwing局域网斗地主

    《JavaSwing局域网斗地主:技术详解与实现剖析》 在计算机科学领域,游戏开发是一项富有挑战性的任务,尤其是局域网内的多人在线游戏。本项目“JavaSwing局域网斗地主”就是一个这样的实例,它充分利用了Java的特性...

    java判断是内网ip还是公网ip

    在Java编程中,判断一个IP地址是内网IP(私有IP)还是公网IP(全局IP)是一项常见的任务,尤其在网络编程和服务器配置中。内网IP通常用于局域网内部通信,而公网IP则是互联网上的唯一标识。下面将详细探讨如何实现这...

    JAVA编写的局域网群聊天软件

    不过,由于描述中提到“如果有外网的服务器IP,理论上支持外网”,这意味着该软件可能已经具备了这样的功能,但是否可行还需要用户自行测试。 总的来说,这个JAVA编写的局域网群聊天软件是一个典型的JAVA网络编程...

    Android开发获取手机内网IP地址与外网IP地址的详细方法与源码实例

    获取外网IP地址的原理是通过访问外网网站,从网站返回的数据中解析本地的IP地址。下面是相应的源码实例: ```java public static String getOutNetIP() { String ipAddress = ""; try { String address = ...

    Java判断IP地址为内网IP还是公网IP的方法

    在Java编程中,判断一个IP地址是内网IP(Private IP)还是公网IP(Public IP)通常涉及到网络通信和TCP/IP协议的理解。TCP/IP协议为了提高网络效率和安全性,将一部分IP地址范围预留给了内部网络使用,这些IP地址...

    精简内外网ip查询工具

    - **IP查询工具**允许用户获取其设备的当前IP地址,包括内网IP和外网IP。这通常通过向特定的网站或应用发送请求来实现,这些网站或应用返回用户的IP信息。 5. 网络诊断: - 这种工具不仅可以显示IP地址,还可以...

    java 局域网监控程序

    在IT领域,局域网监控程序是一种...总的来说,这个Java局域网监控程序是一个强大的工具,能够帮助IT专业人员有效地管理和保护他们的网络环境。通过持续的维护和升级,它可以在不断变化的网络安全环境中发挥重要作用。

    或许本机外网IP和本机IP

    在IT领域,了解和获取本机IP地址以及外网IP地址是常见的需求,尤其是在网络编程、服务器配置或者网络诊断中。下面将详细解释这两个概念及其获取方法。 首先,我们要理解什么是"本机IP"和"外网IP"。 1. 本机IP...

    获取连接手机热点设备的IP地址

    在Android开发中,有时我们需要获取连接到手机热点设备的IP地址,这在设备间通信、网络诊断或构建本地网络服务时特别有用。本教程将详细解释如何实现这一功能,主要涉及"IP地址获取"和"手机AP"这两个关键知识点。 ...

    五、JAVA调用海康威视SDK实现摄像头内网转外网并前端展示

    java调用海康威视sdk摄像头推流到阿里云,并通过ckplayer进行网页播放

    Java局域网聊天系统

    【Java局域网聊天系统】是一种基于Java编程语言开发的通信应用,主要设计用于局域网环境中的用户间即时通讯。这个系统的核心特点是通过输入对方的IP地址来建立连接,从而实现两人之间的文本聊天功能。在理解这个系统...

    局域网聊天室课程设计java

    综上所述,这份局域网聊天室课程设计不仅涵盖了理论知识的学习,更重要的是通过实践让学生掌握了网络编程的基础技能,尤其是在Java环境下实现TCP/IP协议的具体方法。通过这样的实践项目,学生不仅能深入了解网络通信...

    JAVA局域网飞鸽传书软件设计与实现(源代码+论文)

    其次,介绍TCP/IP点对点协议技术,C/S架构和SOCKET网络编程技术;再次,对当前局域网文件传输进行需求分析并提出解决方案;然后,根据解决方案对系统进行设计;最后,对工作计划统计以及分析系统进行测试并得到测试...

    JAVA源码JAVA基于局域网的聊天室系统(源代码+论文)

    ### JAVA源码JAVA基于局域网的聊天室系统(源代码+论文) #### 知识点一:局域网聊天室系统的实现原理 局域网(Local Area Network, LAN)是一种在有限地理区域内连接计算机和其他网络设备的技术。局域网聊天室系统...

    VMware下配置Linux系统局域网和外网访问图文教程

    在VMware中配置Linux系统以实现局域网和外网访问是每个Linux用户的基本技能,尤其是对于初学者来说,这一步至关重要。以下是一份详细的步骤指南,帮助您完成这一过程。 首先,确保您的VMware虚拟机已经安装了Linux...

    Android获取实时连接热点的设备IP

    "Android获取实时连接热点的设备IP" Android获取实时连接热点的设备IP是指在Android系统中获取当前热点连接的设备IP地址的相关技术。主要涉及到Android系统中获取Wifi热点设备的Ip地址的代码实现。 知识点一:/...

    简单实用的邮件主机内网ip和外网ip自动发送程序

    2. **IP地址检测**:程序需要能够获取到邮件主机的内网IP和外网IP。内网IP通常是在局域网内的设备间通信时使用的,可以通过执行`ifconfig`(Linux)或`ipconfig`(Windows)命令获取。外网IP则是互联网上识别邮件...

    Flex通过web返回客户端IP

    4. **处理局域网和外网IP**: - **局域网IP**:在本地测试时,如果Flex应用与Web服务在同一网络环境(例如,都在开发者的局域网内),返回的IP可能是局域网内的IP地址,如192.168.x.x。 - **外网IP**:当应用通过...

    局域网监控源程序.rar

    在局域网监控中,通常会使用编程语言(如C#、Python或Java)编写源程序,通过发送远程桌面请求或者利用VNC(Virtual Network Computing)协议,实现在不被察觉的情况下获取目标计算机的屏幕画面。 三、实现方式 1....

Global site tag (gtag.js) - Google Analytics