我正在尝试开发一个系统,其中有不同的节点运行在不同的系统或在同一系统的不同端口上。

现在,所有节点都创建了一个套接字,将目标IP作为称为引导节点的特殊节点的IP。然后,节点创建自己的ServerSocket并开始侦听连接。

引导节点维护一个节点列表,并在查询时返回它们。

现在我需要的是节点必须将其IP注册到引导节点。我尝试使用cli.getInetAddress()一旦客户端连接到引导节点的ServerSocket,但这不起作用。

我需要客户端注册其PPP IP,如果可用; 否则,局域网IP(如果可用); 否则,它必须注册127.0.0.1,假设它是同一台计算机。

使用代码:

System.out.println(Inet4Address.getLocalHost().getHostAddress());

or

System.out.println(InetAddress.getLocalHost().getHostAddress());

我的PPP连接IP地址是:117.204.44.192,但上面返回我192.168.1.2

EDIT

我正在使用以下代码:

Enumeration e = NetworkInterface.getNetworkInterfaces();
while(e.hasMoreElements())
{
    NetworkInterface n = (NetworkInterface) e.nextElement();
    Enumeration ee = n.getInetAddresses();
    while (ee.hasMoreElements())
    {
        InetAddress i = (InetAddress) ee.nextElement();
        System.out.println(i.getHostAddress());
    }
}

我能够获得所有网络接口相关的所有IP地址,但我如何区分它们?这是我得到的输出:

127.0.0.1
192.168.1.2
192.168.56.1
117.204.44.19

当前回答

private static InetAddress getLocalAddress(){
        try {
            Enumeration<NetworkInterface> b = NetworkInterface.getNetworkInterfaces();
            while( b.hasMoreElements()){
                for ( InterfaceAddress f : b.nextElement().getInterfaceAddresses())
                    if ( f.getAddress().isSiteLocalAddress())
                        return f.getAddress();
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return null;
    }

其他回答

在大多数情况下,这可能有点棘手。

从表面上看,InetAddress.getLocalHost()应该提供该主机的IP地址。问题是一台主机可能有很多网络接口,而一个接口可能绑定到多个IP地址。最重要的是,并不是所有的IP地址都可以在您的机器或局域网之外访问。例如,它们可以是虚拟网络设备的IP地址、私有网络IP地址等等。

这意味着InetAddress.getLocalHost()返回的IP地址可能不是要使用的正确IP地址。

你怎么处理这个问题呢?

One approach is to use NetworkInterface.getNetworkInterfaces() to get all of the known network interfaces on the host, and then iterate over each NI's addresses. Another approach is to (somehow) get the externally advertized FQDN for the host, and use InetAddress.getByName() to look up the primary IP address. (But how do you get it, and how do you deal with a DNS-based load balancer?) A variation of the previous is to get the preferred FQDN from a config file or a command line parameter. Another variation is to get the preferred IP address from a config file or a command line parameter.

总之,InetAddress.getLocalHost()通常可以工作,但是对于代码运行在“复杂”网络环境中的情况,您可能需要提供另一种方法。


我能够获得所有网络接口相关的所有IP地址,但我如何区分它们?

Any address in the range 127.xxx.xxx.xxx is a "loopback" address. It is only visible to "this" host. Any address in the range 192.168.xxx.xxx is a private (aka site local) IP address. These are reserved for use within an organization. The same applies to 10.xxx.xxx.xxx addresses, and 172.16.xxx.xxx through 172.31.xxx.xxx. Addresses in the range 169.254.xxx.xxx are link local IP addresses. These are reserved for use on a single network segment. Addresses in the range 224.xxx.xxx.xxx through 239.xxx.xxx.xxx are multicast addresses. The address 255.255.255.255 is the broadcast address. Anything else should be a valid public point-to-point IPv4 address.

事实上,InetAddress API提供了测试环回、链路本地、站点本地、组播和广播地址的方法。您可以使用这些来分类您获得的哪个IP地址是最合适的。

如果您的机器是网络的一部分,那么它将获取您的网络的IP地址

try {
    System.out.println(InetAddress.getLocalHost().getHostAddress());
} catch (UnknownHostException e) {
    e.printStackTrace();
}

首先导入类

import java.net.InetAddress;

在课堂上

  InetAddress iAddress = InetAddress.getLocalHost();
  String currentIp = iAddress.getHostAddress();
  System.out.println("Current IP address : " +currentIp); //gives only host address

一个相当简单的方法似乎很有效……

String getPublicIPv4() throws UnknownHostException, SocketException{
    Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
    String ipToReturn = null;
    while(e.hasMoreElements())
    {
        NetworkInterface n = (NetworkInterface) e.nextElement();
        Enumeration<InetAddress> ee = n.getInetAddresses();
        while (ee.hasMoreElements())
        {
            InetAddress i = (InetAddress) ee.nextElement();
            String currentAddress = i.getHostAddress();
            logger.trace("IP address "+currentAddress+ " found");
            if(!i.isSiteLocalAddress()&&!i.isLoopbackAddress() && validate(currentAddress)){
                ipToReturn = currentAddress;    
            }else{
                System.out.println("Address not validated as public IPv4");
            }

        }
    }

    return ipToReturn;
}

private static final Pattern IPv4RegexPattern = Pattern.compile(
        "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");

public static boolean validate(final String ip) {
    return IPv4RegexPattern.matcher(ip).matches();
}

一个Kotlin的例子,至少在Windows上可以工作,即使我的VPN是打开的。 (当VPN打开时,其他方法似乎失败了) 它只需要查找一次计算机的IP地址。从那时起,始终可以从存储的适配器信息中找到IP地址。

import java.net.NetworkInterface
import java.util.prefs.Preferences

class WindowsIP {
    companion object {
        val prefs = Preferences.userNodeForPackage(this::class.java)  //Get the current IP address for the wifi adapter whose information
        // has been stored by calling findWifiAdapter(currentIp) with the known current IP (from wifi properties or whatever)
        fun getIpAddress(): String {
            val wlanName = prefs.get("WlanName", "")
            val wlanDisplName = prefs.get("WlanDisplName", "")
            val addrCnt = prefs.getInt("wlanAddrCount", 0)
            val nis = NetworkInterface.getNetworkInterfaces()
            for (ni in nis) {
                if (ni.name == wlanName && ni.displayName == wlanDisplName) {
                    var count = 0
                    for (addr in ni.inetAddresses) {
                        if (count++ == addrCnt) {
                            return addr.hostAddress
                        }
                    }
                }
            }
            return "Unknown. Call findWifiAdapter() with current IP address"
        }

        fun findWifiAdapter(currentIP: String) {  //Find the wifi adapter using the current IP address and store the information
                val nis = NetworkInterface.getNetworkInterfaces()
                for(ni in nis) {
                    var count = 0;
                    for(adr in ni.inetAddresses) {
                        if(adr.hostAddress == currentIP) {
                            prefs.put("WlanName", ni.name)
                            prefs.put("WlanDisplName", ni.displayName)
                            prefs.putInt("wlanAddrCount", count)  //Probably always zero?
                        }
                        ++count
                    }
                }
        }
    }
}