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

com.gateway.connector.utils.NetUtils Maven / Gradle / Ivy


package com.gateway.connector.utils;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.channel.Channel;

public class NetUtils {

	private final static Logger logger = LoggerFactory.getLogger(NetUtils.class);

	/**
	 * 最小端口
	 */
	private static final int MIN_PORT = 0;
	/**
	 * 最大端口
	 */
	private static final int MAX_PORT = 65535;

	/**
	 * 判断端口是否有效 0-65535
	 *
	 * @param port 端口
	 * @return 是否有效
	 */
	public static boolean isInvalidPort(int port) {
		return port > MAX_PORT || port < MIN_PORT;
	}

	/**
	 * 判断端口是否随机端口 小于0表示随机
	 *
	 * @param port 端口
	 * @return 是否随机端口
	 */
	public static boolean isRandomPort(int port) {
		return port < 0;
	}

	/**
	 * 检查当前指定端口是否可用,不可用则自动+1再试(随机端口从默认端口开始检查)
	 *
	 * @param host 当前ip地址
	 * @param port 当前指定端口
	 * @return 从指定端口开始后第一个可用的端口
	 * @throws Exception
	 */
	public static int getAvailablePort(String host, int port) throws Exception {
		if (isAnyHost(host) || isLocalHost(host) || isHostInNetworkCard(host)) {
		} else {
			throw new Exception("The host " + host + " is not found in network cards, please check config");
		}
		if (port < MIN_PORT) {
			port = Consts.DEFAULT_SERVER_PORT;
		}
		for (int i = port; i <= MAX_PORT; i++) {
			ServerSocket ss = null;
			try {
				ss = new ServerSocket();
				ss.bind(new InetSocketAddress(host, i));
				logger.debug("ip:{} port:{" + host + "} is available" + i);
				return i;
			} catch (IOException e) {
				// continue
				logger.warn("Can't bind to address [{" + host + "}:{" + i + "}], "
						+ "Maybe 1) The port has been bound. "
						+ "2) The network card of this host is not exists or disable. " + "3) The host is wrong.");
				logger.info("Begin try next port(auto +1):{" + i + 1 + "}");
			} finally {
				if (ss != null) {
					try {
						ss.close();
					} catch (IOException e) {
					}
				}
			}
		}
		throw new Exception("Can't bind to ANY port of " + host + ", please check config");
	}

	/**
	 * 任意地址
	 */
	public static final String ANYHOST = "0.0.0.0";

	private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$");

	/**
	 * IPv4地址
	 */
	public static final Pattern IPV4_PATTERN = Pattern
			.compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");

	/**
	 * 是否本地地址 127.x.x.x 或者 localhost
	 *
	 * @param host 地址
	 * @return 是否本地地址
	 */
	public static boolean isLocalHost(String host) {
		return StringUtils.isNotBlank(host)
				&& (LOCAL_IP_PATTERN.matcher(host).matches() || "localhost".equalsIgnoreCase(host));
	}

	/**
	 * 是否默认地址 0.0.0.0
	 *
	 * @param host 地址
	 * @return 是否默认地址
	 */
	public static boolean isAnyHost(String host) {
		return ANYHOST.equals(host);
	}

	/**
	 * 是否IPv4地址 0.0.0.0
	 *
	 * @param host 地址
	 * @return 是否默认地址
	 */
	public static boolean isIPv4Host(String host) {
		return StringUtils.isNotBlank(host) && IPV4_PATTERN.matcher(host).matches();
	}

	/**
	 * 是否非法地址(本地或默认)
	 *
	 * @param host 地址
	 * @return 是否非法地址
	 */
	private static boolean isInvalidLocalHost(String host) {
		return StringUtils.isBlank(host) || isAnyHost(host) || isLocalHost(host);
	}

	/**
	 * 是否合法地址(非本地,非默认的IPv4地址)
	 *
	 * @param address InetAddress
	 * @return 是否合法
	 */
	private static boolean isValidAddress(InetAddress address) {
		if (address == null || address.isLoopbackAddress())
			return false;
		String name = address.getHostAddress();
		return (name != null && !isAnyHost(name) && !isLocalHost(name) && isIPv4Host(name));
	}

	/**
	 * 是否网卡上的地址
	 *
	 * @param host 地址
	 * @return 是否默认地址
	 */
	public static boolean isHostInNetworkCard(String host) {
		try {
			InetAddress addr = InetAddress.getByName(host);
			return NetworkInterface.getByInetAddress(addr) != null;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 得到本机IPv4地址
	 *
	 * @return ip地址
	 */
	public static String getLocalHost() {
		InetAddress address = getLocalAddress();
		return address == null ? null : address.getHostAddress();
	}

	/**
	 * 遍历本地网卡,返回第一个合理的IP,保存到缓存中
	 *
	 * @return 本地网卡IP
	 */
	public static InetAddress getLocalAddress() {
		InetAddress localAddress = null;
		try {
			localAddress = InetAddress.getLocalHost();
			if (isValidAddress(localAddress)) {
				return localAddress;
			}
		} catch (Throwable e) {
			logger.warn("Error when retriving ip address: " + e.getMessage(), e);
		}
		try {
			Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
			if (interfaces != null) {
				while (interfaces.hasMoreElements()) {
					try {
						NetworkInterface network = interfaces.nextElement();
						Enumeration addresses = network.getInetAddresses();
						if (addresses != null) {
							while (addresses.hasMoreElements()) {
								try {
									InetAddress address = addresses.nextElement();
									if (isValidAddress(address)) {
										return address;
									}
								} catch (Throwable e) {
									logger.warn("Error when retriving ip address: " + e.getMessage(), e);
								}
							}
						}
					} catch (Throwable e) {
						logger.warn("Error when retriving ip address: " + e.getMessage(), e);
					}
				}
			}
		} catch (Throwable e) {
			logger.warn("Error when retriving ip address: " + e.getMessage(), e);
		}
		logger.error("Can't get valid host, will use 127.0.0.1 instead.");
		return localAddress;
	}

	/**
	 * InetSocketAddress转 host:port 字符串
	 *
	 * @param address InetSocketAddress转
	 * @return host:port 字符串
	 */
	public static String toAddressString(InetSocketAddress address) {
		if (address == null) {
			return StringUtils.EMPTY;
		} else {
			return toIpString(address) + ":" + address.getPort();
		}
	}

	/**
	 * 得到ip地址
	 *
	 * @param address InetSocketAddress
	 * @return ip地址
	 */
	public static String toIpString(InetSocketAddress address) {
		if (address == null) {
			return null;
		} else {
			InetAddress inetAddress = address.getAddress();
			return inetAddress == null ? address.getHostName() : inetAddress.getHostAddress();
		}
	}

	/**
	 * 本地多ip情况下、连一下注册中心地址得到本地IP地址
	 *
	 * @param registryIp 注册中心地址
	 * @return 本地多ip情况下得到本地能连上注册中心的IP地址
	 */
	public static String getLocalHostByRegistry(String registryIp) {
		String host = null;
		if (registryIp != null && registryIp.length() > 0) {
			List addrs = getIpListByRegistry(registryIp);
			for (int i = 0; i < addrs.size(); i++) {
				InetAddress address = getLocalHostBySocket(addrs.get(i));
				if (address != null) {
					host = address.getHostAddress();
					if (host != null && !NetUtils.isInvalidLocalHost(host)) {
						return host;
					}
				}
			}
		}
		if (NetUtils.isInvalidLocalHost(host)) {
			host = NetUtils.getLocalHost();
		}
		return host;
	}

	/**
	 * 通过连接远程地址得到本机内网地址
	 *
	 * @param remoteAddress 远程地址
	 * @return 本机内网地址
	 */
	private static InetAddress getLocalHostBySocket(InetSocketAddress remoteAddress) {
		InetAddress host = null;
		try {
			// 去连一下远程地址
			Socket socket = new Socket();
			try {
				socket.connect(remoteAddress, 1000);
				// 得到本地地址
				host = socket.getLocalAddress();
			} finally {
				try {
					socket.close();
				} catch (Throwable e) {
					logger.warn("NetUtils getLocalHostBySocket occur Exception!", e);
				}
			}
		} catch (Exception e) {
			logger.warn(
					"Can not connect to host {" + remoteAddress.toString() + "}, cause by :{" + e.getMessage() + "}");
		}
		return host;
	}

	/**
	 * 解析注册中心地址配置为多个连接地址
	 *
	 * @param registryIp 注册中心地址
	 * @return
	 */
	public static List getIpListByRegistry(String registryIp) {
		List ips = new ArrayList();
		String defaultPort = null;

		String[] srcIps = registryIp.split(",");
		for (String add : srcIps) {
			int a = add.indexOf("://");
			if (a > -1) {
				add = add.substring(a + 3); // 去掉协议头
			}
			String[] s1 = add.split(":");
			if (s1.length > 1) {
				if (defaultPort == null && s1[1] != null && s1[1].length() > 0) {
					defaultPort = s1[1];
				}
				ips.add(new String[] { s1[0], s1[1] }); // 得到ip和端口
			} else {
				ips.add(new String[] { s1[0], defaultPort });
			}
		}

		List ads = new ArrayList();
		for (int j = 0; j < ips.size(); j++) {
			String[] ip = ips.get(j);
			try {
				InetSocketAddress address = new InetSocketAddress(ip[0],
						Integer.parseInt(ip[1] == null ? defaultPort : ip[1]));
				ads.add(address);
			} catch (Exception e) {
				logger.warn("NetUtils getIpListByRegistry occur Exception!", e);
			}
		}

		return ads;
	}

	/**
	 * 判断当前ip是否符合白名单
	 *
	 * @param whitelist 白名单,可以配置为*
	 * @param localIP   当前地址
	 * @return
	 */
	public static boolean isMatchIPByPattern(String whitelist, String localIP) {
		if (StringUtils.isNotBlank(whitelist)) {
			if ("*".equals(whitelist)) {
				return true;
			}
			for (String ips : whitelist.replace(',', ';').split(";", -1)) {
				try {
					if (ips.contains("*")) { // 带通配符
						String regex = ips.trim().replace(".", "\\.").replace("*", ".*");
						Pattern pattern = Pattern.compile(regex);
						if (pattern.matcher(localIP).find()) {
							return true;
						}
					} else if (!isIPv4Host(ips)) { // 不带通配符的正则表达式
						String regex = ips.trim().replace(".", "\\.");
						Pattern pattern = Pattern.compile(regex);
						if (pattern.matcher(localIP).find()) {
							return true;
						}
					} else {
						if (ips.equals(localIP)) {
							return true;
						}
					}
				} catch (Exception e) {
					logger.warn("syntax of pattern {" + ips + "} is invalid");
				}
			}
		}
		return false;
	}

	/**
	 * 连接转字符串
	 *
	 * @param local  本地地址
	 * @param remote 远程地址
	 * @return
	 */
	public static String connectToString(InetSocketAddress local, InetSocketAddress remote) {
		return toAddressString(local) + " <-> " + toAddressString(remote);
	}

	/**
	 * 连接转字符串
	 *
	 * @param local1  本地地址
	 * @param remote1 远程地址
	 * @return
	 */
	public static String channelToString(SocketAddress local1, SocketAddress remote1) {
		try {
			InetSocketAddress local = (InetSocketAddress) local1;
			InetSocketAddress remote = (InetSocketAddress) remote1;
			return toAddressString(local) + " -> " + toAddressString(remote);
		} catch (Exception e) {
			return local1 + "->" + remote1;
		}
	}

	/**
	 * 是否可以telnet
	 *
	 * @param ip      远程地址
	 * @param port    远程端口
	 * @param timeout 连接超时
	 * @return 是否可连接
	 */
	public static boolean canTelnet(String ip, int port, int timeout) {
		Socket socket = null;
		try {
			socket = new Socket();
			socket.connect(new InetSocketAddress(ip, port), timeout);
			return socket.isConnected();
		} catch (Exception e) {
			logger.warn("NetUtils canTelnet occur Exception!", e);
			return false;
		} finally {
			if (socket != null) {
				try {
					socket.close();
				} catch (IOException e) {
				}
			}
		}
	}

	public static String getTransportKey(String ip, int port) {
		return ip + "::" + port;
	}

	public static String getClientTransportKey(String protocolName, String ip, int port) {
		return protocolName + "::" + ip + "::" + port;
	}

	public static String getTransportKey(Channel channel) {
		String str = "";
		InetSocketAddress address = (InetSocketAddress) channel.remoteAddress();
		if (address != null) {
			String remoteIp = NetUtils.toIpString(address);
			int port = address.getPort();
			str = getTransportKey(remoteIp, port);
		}
		return str;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy