我正在尝试开发一个系统,其中有不同的节点运行在不同的系统或在同一系统的不同端口上。
现在,所有节点都创建了一个套接字,将目标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
import java.net.DatagramSocket;
import java.net.InetAddress;
try(final DatagramSocket socket = new DatagramSocket()){
socket.connect(InetAddress.getByName("8.8.8.8"), 10002);
ip = socket.getLocalAddress().getHostAddress();
}
这种方式适用于有多个网络接口的情况。它总是返回首选出站IP。目的地8.8.8.8不需要可达。
Connect on a UDP socket has the following effect: it sets the destination for Send/Recv, discards all packets from other addresses, and - which is what we use - transfers the socket into "connected" state, settings its appropriate fields. This includes checking the existence of the route to the destination according to the system's routing table and setting the local endpoint accordingly. The last part seems to be undocumented officially but it looks like an integral trait of Berkeley sockets API (a side effect of UDP "connected" state) that works reliably in both Windows and Linux across versions and distributions.
因此,此方法将提供用于连接到指定远程主机的本地地址。没有建立真正的连接,因此指定的远端ip不可达。
编辑:
正如@macomgil所说,对于MacOS,你可以这样做:
Socket socket = new Socket();
socket.connect(new InetSocketAddress("google.com", 80));
System.out.println(socket.getLocalAddress());
编辑1:更新后的代码,因为之前的链接,不再存在
import java.io.*;
import java.net.*;
public class GetMyIP {
public static void main(String[] args) {
URL url = null;
BufferedReader in = null;
String ipAddress = "";
try {
url = new URL("http://bot.whatismyipaddress.com");
in = new BufferedReader(new InputStreamReader(url.openStream()));
ipAddress = in.readLine().trim();
/* IF not connected to internet, then
* the above code will return one empty
* String, we can check it's length and
* if length is not greater than zero,
* then we can go for LAN IP or Local IP
* or PRIVATE IP
*/
if (!(ipAddress.length() > 0)) {
try {
InetAddress ip = InetAddress.getLocalHost();
System.out.println((ip.getHostAddress()).trim());
ipAddress = (ip.getHostAddress()).trim();
} catch(Exception exp) {
ipAddress = "ERROR";
}
}
} catch (Exception ex) {
// This try will give the Private IP of the Host.
try {
InetAddress ip = InetAddress.getLocalHost();
System.out.println((ip.getHostAddress()).trim());
ipAddress = (ip.getHostAddress()).trim();
} catch(Exception exp) {
ipAddress = "ERROR";
}
//ex.printStackTrace();
}
System.out.println("IP Address: " + ipAddress);
}
}
实际版本:这停止工作
希望这段代码可以帮助你实现这一点:
// Method to get the IP Address of the Host.
private String getIP()
{
// This try will give the Public IP Address of the Host.
try
{
URL url = new URL("http://automation.whatismyip.com/n09230945.asp");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String ipAddress = new String();
ipAddress = (in.readLine()).trim();
/* IF not connected to internet, then
* the above code will return one empty
* String, we can check it's length and
* if length is not greater than zero,
* then we can go for LAN IP or Local IP
* or PRIVATE IP
*/
if (!(ipAddress.length() > 0))
{
try
{
InetAddress ip = InetAddress.getLocalHost();
System.out.println((ip.getHostAddress()).trim());
return ((ip.getHostAddress()).trim());
}
catch(Exception ex)
{
return "ERROR";
}
}
System.out.println("IP Address is : " + ipAddress);
return (ipAddress);
}
catch(Exception e)
{
// This try will give the Private IP of the Host.
try
{
InetAddress ip = InetAddress.getLocalHost();
System.out.println((ip.getHostAddress()).trim());
return ((ip.getHostAddress()).trim());
}
catch(Exception ex)
{
return "ERROR";
}
}
}
一个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
}
}
}
}
}