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

现在,所有节点都创建了一个套接字,将目标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

当前回答

使用InetAddress.getLocalHost()获取本地地址

import java.net.InetAddress;

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

其他回答

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

从表面上看,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地址是最合适的。

使用InetAddress.getLocalHost()获取本地地址

import java.net.InetAddress;

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

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

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();
}

在寻找“本地”地址时,应该注意到每台机器不仅只有一个网络接口,而且每个接口可以有自己的本地地址。这意味着您的机器总是拥有几个“本地”地址。

当您连接到不同的端点时,将自动选择使用不同的“本地”地址。例如,当你连接到google.com时,你是在使用一个“外部”本地地址;但是当您连接到本地主机时,您的本地地址总是localhost本身,因为localhost只是一个环回。

下面是当你与google.com通信时如何找到你的本地地址:

Socket socket = new Socket();
socket.connect(new InetSocketAddress("google.com", 80));
System.out.println(socket.getLocalAddress());
socket.close();

你可以使用java的InetAddress类来实现这个目的。

InetAddress IP=InetAddress.getLocalHost();
System.out.println("IP of my system is := "+IP.getHostAddress());

my system = IP的输出是:= 10.100.98.228

getHostAddress()返回

以文本形式返回IP地址字符串。

或者你也可以这样做

InetAddress IP=InetAddress.getLocalHost();
System.out.println(IP.toString());

我的系统Output = IP为:= RanRag-PC/10.100.98.228