All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xiaoleilu.hutool.util.NetUtil Maven / Gradle / Ivy

package com.xiaoleilu.hutool.util;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.SocketException;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedHashSet;

import com.xiaoleilu.hutool.collection.CollectionUtil;
import com.xiaoleilu.hutool.exceptions.UtilException;
import com.xiaoleilu.hutool.io.IORuntimeException;
import com.xiaoleilu.hutool.io.IoUtil;
import com.xiaoleilu.hutool.lang.Validator;

/**
 * 网络相关工具
 * 
 * @author xiaoleilu
 *
 */
public class NetUtil {
	public final static String LOCAL_IP = "127.0.0.1";

	/**
	 * 根据long值获取ip v4地址
	 * 
	 * @param longIP IP的long表示形式
	 * @return IP V4 地址
	 */
	public static String longToIpv4(long longIP) {
		final StringBuilder sb = new StringBuilder();
		// 直接右移24位
		sb.append(String.valueOf(longIP >>> 24));
		sb.append(".");
		// 将高8位置0,然后右移16位
		sb.append(String.valueOf((longIP & 0x00FFFFFF) >>> 16));
		sb.append(".");
		sb.append(String.valueOf((longIP & 0x0000FFFF) >>> 8));
		sb.append(".");
		sb.append(String.valueOf(longIP & 0x000000FF));
		return sb.toString();
	}

	/**
	 * 根据ip地址计算出long型的数据
	 * 
	 * @param strIP IP V4 地址
	 * @return long值
	 */
	public static long ipv4ToLong(String strIP) {
		if (Validator.isIpv4(strIP)) {
			long[] ip = new long[4];
			// 先找到IP地址字符串中.的位置
			int position1 = strIP.indexOf(".");
			int position2 = strIP.indexOf(".", position1 + 1);
			int position3 = strIP.indexOf(".", position2 + 1);
			// 将每个.之间的字符串转换成整型
			ip[0] = Long.parseLong(strIP.substring(0, position1));
			ip[1] = Long.parseLong(strIP.substring(position1 + 1, position2));
			ip[2] = Long.parseLong(strIP.substring(position2 + 1, position3));
			ip[3] = Long.parseLong(strIP.substring(position3 + 1));
			return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
		}
		return 0;
	}

	/**
	 * 检测本地端口可用性
	 * 
	 * @param port 被检测的端口
	 * @return 是否可用
	 */
	public static boolean isUsableLocalPort(int port) {
		if (false == isValidPort(port)) {
			// 给定的IP未在指定端口范围中
			return false;
		}
		try {
			new Socket(LOCAL_IP, port).close();
			// socket链接正常,说明这个端口正在使用
			return false;
		} catch (Exception e) {
			return true;
		}
	}

	/**
	 * 是否为有效的端口
	 * 
	 * @param port 端口号
	 * @return 是否有效
	 */
	public static boolean isValidPort(int port) {
		// 有效端口是0~65535
		return port >= 0 && port <= 0xFFFF;
	}

	/**
	 * 判定是否为内网IP
* 私有IP:A类 10.0.0.0-10.255.255.255 B类 172.16.0.0-172.31.255.255 C类 192.168.0.0-192.168.255.255 当然,还有127这个网段是环回地址 * * @param ipAddress IP地址 * @return 是否为内网IP */ public static boolean isInnerIP(String ipAddress) { boolean isInnerIp = false; long ipNum = NetUtil.ipv4ToLong(ipAddress); long aBegin = NetUtil.ipv4ToLong("10.0.0.0"); long aEnd = NetUtil.ipv4ToLong("10.255.255.255"); long bBegin = NetUtil.ipv4ToLong("172.16.0.0"); long bEnd = NetUtil.ipv4ToLong("172.31.255.255"); long cBegin = NetUtil.ipv4ToLong("192.168.0.0"); long cEnd = NetUtil.ipv4ToLong("192.168.255.255"); isInnerIp = isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd) || ipAddress.equals(LOCAL_IP); return isInnerIp; } /** * 相对URL转换为绝对URL * * @param absoluteBasePath 基准路径,绝对 * @param relativePath 相对路径 * @return 绝对URL */ public static String toAbsoluteUrl(String absoluteBasePath, String relativePath) { try { URL absoluteUrl = new URL(absoluteBasePath); return new URL(absoluteUrl, relativePath).toString(); } catch (Exception e) { throw new UtilException(StrUtil.format("To absolute url [{}] base [{}] error!", relativePath, absoluteBasePath), e); } } /** * 隐藏掉IP地址的最后一部分为 * 代替 * * @param ip IP地址 * @return 隐藏部分后的IP */ public static String hideIpPart(String ip) { return new StringBuffer(ip.length()).append(ip.substring(0, ip.lastIndexOf(".") + 1)).append("*").toString(); } /** * 隐藏掉IP地址的最后一部分为 * 代替 * * @param ip IP地址 * @return 隐藏部分后的IP */ public static String hideIpPart(long ip) { return hideIpPart(longToIpv4(ip)); } /** * 构建InetSocketAddress
* 当host中包含端口时(用“:”隔开),使用host中的端口,否则使用默认端口
* 给定host为空时使用本地host(127.0.0.1) * * @param host Host * @param defaultPort 默认端口 * @return InetSocketAddress */ public static InetSocketAddress buildInetSocketAddress(String host, int defaultPort) { if (StrUtil.isBlank(host)) { host = LOCAL_IP; } String destHost = null; int port = 0; int index = host.indexOf(":"); if (index != -1) { // host:port形式 destHost = host.substring(0, index); port = Integer.parseInt(host.substring(index + 1)); } else { destHost = host; port = defaultPort; } return new InetSocketAddress(destHost, port); } /** * 通过域名得到IP * * @param hostName HOST * @return ip address or hostName if UnknownHostException */ public static String getIpByHost(String hostName) { try { return InetAddress.getByName(hostName).getHostAddress(); } catch (UnknownHostException e) { return hostName; } } /** * 获取本机所有网卡 * * @return 所有网卡,异常返回null * @since 3.0.1 */ public static Collection getNetworkInterfaces() { Enumeration networkInterfaces = null; try { networkInterfaces = NetworkInterface.getNetworkInterfaces(); } catch (SocketException e) { return null; } return CollectionUtil.addAll(new ArrayList(), networkInterfaces); } /** * 获得本机的IP地址列表
* 返回的IP列表有序,按照系统设备顺序 * * @return IP地址列表 {@link LinkedHashSet} */ public static LinkedHashSet localIpv4s() { Enumeration networkInterfaces = null; try { networkInterfaces = NetworkInterface.getNetworkInterfaces(); } catch (SocketException e) { throw new UtilException(e.getMessage(), e); } if (networkInterfaces == null) { throw new UtilException("Get network interface error!"); } final LinkedHashSet ipSet = new LinkedHashSet<>(); while (networkInterfaces.hasMoreElements()) { final NetworkInterface networkInterface = networkInterfaces.nextElement(); final Enumeration inetAddresses = networkInterface.getInetAddresses(); while (inetAddresses.hasMoreElements()) { final InetAddress inetAddress = inetAddresses.nextElement(); if (inetAddress != null && inetAddress instanceof Inet4Address) { ipSet.add(inetAddress.getHostAddress()); } } } return ipSet; } /** * 获取本机网卡IP地址,这个地址为所有网卡中非回路地址的第一个
* 如果获取失败调用 {@link InetAddress#getLocalHost()}方法获取。
* 此方法不会抛出异常,获取失败将返回null
* * 参考:http://stackoverflow.com/questions/9481865/getting-the-ip-address-of-the-current-machine-using-java * * @return 本机网卡IP地址,获取失败返回null * @since 3.0.7 */ public static String getLocalhostStr() { InetAddress localhost = getLocalhost(); if (null != localhost) { return localhost.getHostAddress(); } return null; } /** * 获取本机网卡IP地址,这个地址为所有网卡中非回路地址的第一个
* 如果获取失败调用 {@link InetAddress#getLocalHost()}方法获取。
* 此方法不会抛出异常,获取失败将返回null
* * 参考:http://stackoverflow.com/questions/9481865/getting-the-ip-address-of-the-current-machine-using-java * * @return 本机网卡IP地址,获取失败返回null * @since 3.0.1 */ public static InetAddress getLocalhost() { InetAddress candidateAddress = null; NetworkInterface iface; InetAddress inetAddr; try { for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) { iface = ifaces.nextElement(); for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) { inetAddr = inetAddrs.nextElement(); if (false == inetAddr.isLoopbackAddress()) { if (inetAddr.isSiteLocalAddress()) { return inetAddr; } else if (null == candidateAddress) { // 非site-local地址做为候选地址返回 candidateAddress = inetAddr; } } } } } catch (SocketException e) { // ignore socket exception, and return null; } if (null == candidateAddress) { try { candidateAddress = InetAddress.getLocalHost(); } catch (UnknownHostException e) { // ignore } } return candidateAddress; } /** * 获得本机MAC地址 * * @return 本机MAC地址 */ public static String getLocalMacAddress() { return getMacAddress(getLocalhost()); } /** * 获得指定地址信息中的MAC地址,使用分隔符“-” * * @param inetAddress {@link InetAddress} * @return MAC地址,用-分隔 */ public static String getMacAddress(InetAddress inetAddress) { return getMacAddress(inetAddress, "-"); } /** * 获得指定地址信息中的MAC地址 * * @param inetAddress {@link InetAddress} * @param separator 分隔符,推荐使用“-”或者“:” * @return MAC地址,用-分隔 */ public static String getMacAddress(InetAddress inetAddress, String separator) { if (null == inetAddress) { return null; } byte[] mac; try { mac = NetworkInterface.getByInetAddress(inetAddress).getHardwareAddress(); } catch (SocketException e) { throw new UtilException(e); } if (null != mac) { final StringBuilder sb = new StringBuilder(); String s; for (int i = 0; i < mac.length; i++) { if (i != 0) { sb.append(separator); } // 字节转换为整数 s = Integer.toHexString(mac[i] & 0xFF); sb.append(s.length() == 1 ? 0 + s : s); } return sb.toString(); } return null; } /** * 创建 {@link InetSocketAddress} * @param host 域名或IP地址 * @param port 端口 * @return {@link InetSocketAddress} * @since 3.3.0 */ public static InetSocketAddress createAddress(String host, int port) { return new InetSocketAddress(host, port); } /** * * 简易的使用Socket发送数据 * * @param host Server主机 * @param port Server端口 * @param isBlock 是否阻塞方式 * @param data 需要发送的数据 * @throws IORuntimeException IO异常 * @since 3.3.0 */ public static void netCat(String host, int port, boolean isBlock, ByteBuffer data) throws IORuntimeException { try (SocketChannel channel = SocketChannel.open(createAddress(host, port))) { channel.configureBlocking(isBlock); channel.write(data); } catch (IOException e) { throw new IORuntimeException(e); } } /** * * 使用普通Socket发送数据 * * @param host Server主机 * @param port Server端口 * @param data 数据 * @throws IOException IO异常 * @since 3.3.0 */ public static void netCat(String host, int port, byte[] data) throws IORuntimeException { OutputStream out = null; try (Socket socket = new Socket(host, port)) { out = socket.getOutputStream(); out.write(data); out.flush(); } catch (IOException e) { throw new IORuntimeException(e); } finally { IoUtil.close(out); } } // ----------------------------------------------------------------------------------------- Private method start /** * 指定IP的long是否在指定范围内 * * @param userIp 用户IP * @param begin 开始IP * @param end 结束IP * @return 是否在范围内 */ private static boolean isInner(long userIp, long begin, long end) { return (userIp >= begin) && (userIp <= end); } // ----------------------------------------------------------------------------------------- Private method end }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy