我正在尝试开发一个系统,其中有不同的节点运行在不同的系统或在同一系统的不同端口上。
现在,所有节点都创建了一个套接字,将目标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
一个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
}
}
}
}
}
在这里发布来自https://issues.apache.org/jira/browse/JCS-40的测试IP歧义变通代码(InetAddress.getLocalHost()在Linux系统上是歧义的):
/**
* Returns an <code>InetAddress</code> object encapsulating what is most likely the machine's LAN IP address.
* <p/>
* This method is intended for use as a replacement of JDK method <code>InetAddress.getLocalHost</code>, because
* that method is ambiguous on Linux systems. Linux systems enumerate the loopback network interface the same
* way as regular LAN network interfaces, but the JDK <code>InetAddress.getLocalHost</code> method does not
* specify the algorithm used to select the address returned under such circumstances, and will often return the
* loopback address, which is not valid for network communication. Details
* <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4665037">here</a>.
* <p/>
* This method will scan all IP addresses on all network interfaces on the host machine to determine the IP address
* most likely to be the machine's LAN address. If the machine has multiple IP addresses, this method will prefer
* a site-local IP address (e.g. 192.168.x.x or 10.10.x.x, usually IPv4) if the machine has one (and will return the
* first site-local address if the machine has more than one), but if the machine does not hold a site-local
* address, this method will return simply the first non-loopback address found (IPv4 or IPv6).
* <p/>
* If this method cannot find a non-loopback address using this selection algorithm, it will fall back to
* calling and returning the result of JDK method <code>InetAddress.getLocalHost</code>.
* <p/>
*
* @throws UnknownHostException If the LAN address of the machine cannot be found.
*/
private static InetAddress getLocalHostLANAddress() throws UnknownHostException {
try {
InetAddress candidateAddress = null;
// Iterate all NICs (network interface cards)...
for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
// Iterate all IP addresses assigned to each card...
for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
if (!inetAddr.isLoopbackAddress()) {
if (inetAddr.isSiteLocalAddress()) {
// Found non-loopback site-local address. Return it immediately...
return inetAddr;
}
else if (candidateAddress == null) {
// Found non-loopback address, but not necessarily site-local.
// Store it as a candidate to be returned if site-local address is not subsequently found...
candidateAddress = inetAddr;
// Note that we don't repeatedly assign non-loopback non-site-local addresses as candidates,
// only the first. For subsequent iterations, candidate will be non-null.
}
}
}
}
if (candidateAddress != null) {
// We did not find a site-local address, but we found some other non-loopback address.
// Server might have a non-site-local address assigned to its NIC (or it might be running
// IPv6 which deprecates the "site-local" concept).
// Return this non-loopback candidate address...
return candidateAddress;
}
// At this point, we did not find a non-loopback address.
// Fall back to returning whatever InetAddress.getLocalHost() returns...
InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
if (jdkSuppliedAddress == null) {
throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
}
return jdkSuppliedAddress;
}
catch (Exception e) {
UnknownHostException unknownHostException = new UnknownHostException("Failed to determine LAN address: " + e);
unknownHostException.initCause(e);
throw unknownHostException;
}
}