Получение IP-адреса текущего компьютера с использованием Java
Я пытаюсь разработать систему, в которой есть разные узлы, которые работают на разных системах или на разных портах в одной системе.
Теперь все узлы создают Socket с целевым IP-адресом в качестве IP-адреса специального узла, называемого узлом начальной загрузки. Затем узлы создают свои собственные ServerSocket
и начать слушать соединения.
Узел начальной загрузки поддерживает список узлов и возвращает их при запросе.
Теперь мне нужно, чтобы узел зарегистрировал свой IP на узле начальной загрузки. Я пытался с помощью cli.getInetAddress()
как только клиент подключается к ServerSocket
загрузочного узла, но это не сработало.
- Мне нужно, чтобы клиент зарегистрировал свой PPP IP, если он доступен;
- В противном случае IP-адрес ЛВС, если имеется
- В противном случае он должен зарегистрировать 127.0.0.1, предполагая, что это тот же компьютер.
Используя код:
System.out.println(Inet4Address.getLocalHost().getHostAddress());
или же
System.out.println(InetAddress.getLocalHost().getHostAddress());
Мой IP-адрес соединения PPP: 117.204.44.192, но вышеприведенное возвращает мне 192.168.1.2
РЕДАКТИРОВАТЬ
Я использую следующий код:
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-адреса, связанные со всеми NetworkInterface
s, но как я могу их различить? Это вывод, который я получаю:
127.0.0.1
192.168.1.2
192.168.56.1
117.204.44.19
20 ответов
import java.net.DatagramSocket;
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
на UDP-сокете имеет следующий эффект: он устанавливает пункт назначения для отправки / записи, отбрасывает все пакеты с других адресов и - что мы и используем - переводит сокет в "подключенное" состояние, устанавливает соответствующие поля. Это включает в себя проверку существования маршрута к пункту назначения в соответствии с таблицей маршрутизации системы и соответствующей настройкой локальной конечной точки. Последняя часть, кажется, официально не документирована, но выглядит как неотъемлемая черта API сокетов Berkeley (побочный эффект состояния UDP "подключен"), который надежно работает как в Windows, так и в Linux в разных версиях и дистрибутивах.
Таким образом, этот метод даст локальный адрес, который будет использоваться для подключения к указанному удаленному хосту. Реальное соединение не установлено, поэтому указанный удаленный IP-адрес может быть недоступен.
Это может быть немного сложнее в самом общем случае.
На первый взгляд, InetAddress.getLocalHost()
должен дать вам IP-адрес этого хоста. Проблема заключается в том, что хост может иметь множество сетевых интерфейсов, и интерфейс может быть связан с несколькими IP-адресами. Кроме того, не все IP-адреса будут доступны за пределами вашей машины или локальной сети. Например, это могут быть IP-адреса для виртуальных сетевых устройств, IP-адреса частных сетей и т. Д.
Это означает, что IP-адрес возвращается InetAddress.getLocalHost()
не может быть правильным для использования.
Как вы можете справиться с этим?
- Один подход заключается в использовании
NetworkInterface.getNetworkInterfaces()
получить все известные сетевые интерфейсы на хосте, а затем выполнить итерацию по адресам каждого NI. - Другой подход заключается в том, чтобы (каким-то образом) получить внешнее полное доменное имя, рекламируемое извне, и использовать
InetAddress.getByName()
искать первичный IP-адрес. (Но как вы это получаете, и как вы справляетесь с балансировщиком нагрузки на основе DNS?) - Разновидностью предыдущего является получение предпочтительного полного доменного имени из файла конфигурации или параметра командной строки.
- Другой вариант - получить предпочтительный IP-адрес из файла конфигурации или параметра командной строки.
В итоге, InetAddress.getLocalHost()
обычно будет работать, но вам может потребоваться предоставить альтернативный метод для случаев, когда ваш код выполняется в среде со "сложной" сетью.
Я могу получить все IP-адреса, связанные со всеми сетевыми интерфейсами, но как я могу их различить?
- Любой адрес в диапазоне 127.xxx.xxx.xxx является адресом обратной связи. Он виден только "этому" хосту.
- Любой адрес в диапазоне 192.168.xxx.xxx является частным (он же локальный IP-адрес сайта). Они зарезервированы для использования в организации. То же самое относится к адресам 10.xxx.xxx.xxx и 172.16.xxx.xxx - 172.31.xxx.xxx.
- Адреса в диапазоне 169.254.xxx.xxx являются локальными IP-адресами связи. Они зарезервированы для использования в одном сегменте сети.
- Адреса в диапазоне от 224.xxx.xxx.xxx до 239.xxx.xxx.xxx являются многоадресными адресами.
- Адрес 255.255.255.255 является широковещательным адресом.
- Все остальное должно быть действительным общедоступным двухточечным IPv4-адресом.
На самом деле API InetAddress предоставляет методы для проверки обратной связи, локальных ссылок, локальных сайтов, многоадресных и широковещательных адресов. Вы можете использовать их, чтобы выбрать наиболее подходящий IP-адрес.
Размещение здесь проверенного кода обхода неоднозначности IP-адреса с https://issues.apache.org/jira/browse/JCS-40 (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;
}
}
Для этой цели вы можете использовать Java-класс InetAddress.
InetAddress IP=InetAddress.getLocalHost();
System.out.println("IP of my system is := "+IP.getHostAddress());
Выход для моей системы = IP of my system is := 10.100.98.228
getHostAddress () возвращает
Возвращает строку IP-адреса в текстовом представлении.
ИЛИ вы также можете сделать
InetAddress IP=InetAddress.getLocalHost();
System.out.println(IP.toString());
Выход = IP of my system is := RanRag-PC/10.100.98.228
Когда вы ищете свой "локальный" адрес, вы должны заметить, что каждая машина имеет не только один сетевой интерфейс, и каждый интерфейс может иметь свой собственный локальный адрес. Это означает, что ваша машина всегда владеет несколькими "локальными" адресами.
Различные "локальные" адреса будут автоматически выбраны для использования при подключении к различным конечным точкам. Например, когда вы подключаетесь к google.com
вы используете "внешний" локальный адрес; но когда вы подключаетесь к localhost
Ваш локальный адрес всегда localhost
само по себе, потому что localhost - это просто петля.
Ниже показано, как узнать ваш локальный адрес, когда вы общаетесь с google.com
:
Socket socket = new Socket();
socket.connect(new InetSocketAddress("google.com", 80));
System.out.println(socket.getLocalAddress());
Пример в scala (полезно в файле sbt):
import collection.JavaConverters._
import java.net._
def getIpAddress: String = {
val enumeration = NetworkInterface.getNetworkInterfaces.asScala.toSeq
val ipAddresses = enumeration.flatMap(p =>
p.getInetAddresses.asScala.toSeq
)
val address = ipAddresses.find { address =>
val host = address.getHostAddress
host.contains(".") && !address.isLoopbackAddress
}.getOrElse(InetAddress.getLocalHost)
address.getHostAddress
}
РЕДАКТИРОВАТЬ 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";
}
}
}
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;
}
Во -первых импортировать класс
import java.net.InetAddress;
в классе
InetAddress iAddress = InetAddress.getLocalHost();
String currentIp = iAddress.getHostAddress();
System.out.println("Current IP address : " +currentIp); //gives only host address
Ты можешь использовать java.net.InetAddress
API. Попробуй это:
InetAddress.getLocalHost().getHostAddress();
Это рабочий пример ПРИНЯТОГО ответа выше! Этот класс NetIdentity будет хранить как внутренний IP-адрес хоста, так и локальную петлю. Если вы работаете на DNS-сервере, как упоминалось выше, вам может потребоваться добавить еще несколько проверок или, возможно, перейти в раздел "Файл конфигурации".
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
/**
* Class that allows a device to identify itself on the INTRANET.
*
* @author Decoded4620 2016
*/
public class NetIdentity {
private String loopbackHost = "";
private String host = "";
private String loopbackIp = "";
private String ip = "";
public NetIdentity(){
try{
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while(interfaces.hasMoreElements()){
NetworkInterface i = interfaces.nextElement();
if(i != null){
Enumeration<InetAddress> addresses = i.getInetAddresses();
System.out.println(i.getDisplayName());
while(addresses.hasMoreElements()){
InetAddress address = addresses.nextElement();
String hostAddr = address.getHostAddress();
// local loopback
if(hostAddr.indexOf("127.") == 0 ){
this.loopbackIp = address.getHostAddress();
this.loopbackHost = address.getHostName();
}
// internal ip addresses (behind this router)
if( hostAddr.indexOf("192.168") == 0 ||
hostAddr.indexOf("10.") == 0 ||
hostAddr.indexOf("172.16") == 0 ){
this.host = address.getHostName();
this.ip = address.getHostAddress();
}
System.out.println("\t\t-" + address.getHostName() + ":" + address.getHostAddress() + " - "+ address.getAddress());
}
}
}
}
catch(SocketException e){
}
try{
InetAddress loopbackIpAddress = InetAddress.getLocalHost();
this.loopbackIp = loopbackIpAddress.getHostName();
System.out.println("LOCALHOST: " + loopbackIp);
}
catch(UnknownHostException e){
System.err.println("ERR: " + e.toString());
}
}
public String getLoopbackHost(){
return loopbackHost;
}
public String getHost(){
return host;
}
public String getIp(){
return ip;
}
public String getLoopbackIp(){
return loopbackIp;
}
}
Когда я запускаю этот код, я на самом деле получаю распечатку так:
Software Loopback Interface 1
-127.0.0.1:127.0.0.1 - [B@19e1023e
-0:0:0:0:0:0:0:1:0:0:0:0:0:0:0:1 - [B@7cef4e59
Broadcom 802.11ac Network Adapter
-VIKING.yourisp.com:192.168.1.142 - [B@64b8f8f4
-fe80:0:0:0:81fa:31d:21c9:85cd%wlan0:fe80:0:0:0:81fa:31d:21c9:85cd%wlan0 - [B@2db0f6b2
Microsoft Kernel Debug Network Adapter
Intel Edison USB RNDIS Device
Driver for user-mode network applications
Cisco Systems VPN Adapter for 64-bit Windows
VirtualBox Host-Only Ethernet Adapter
-VIKING:192.168.56.1 - [B@3cd1f1c8
-VIKING:fe80:0:0:0:d599:3cf0:5462:cb7%eth4 - [B@3a4afd8d
LogMeIn Hamachi Virtual Ethernet Adapter
-VIKING:25.113.118.39 - [B@1996cd68
-VIKING:2620:9b:0:0:0:0:1971:7627 - [B@3339ad8e
-VIKING:fe80:0:0:0:51bf:994d:4656:8486%eth5 - [B@555590
Bluetooth Device (Personal Area Network)
-fe80:0:0:0:4c56:8009:2bca:e16b%eth6:fe80:0:0:0:4c56:8009:2bca:e16b%eth6 - [B@3c679bde
Bluetooth Device (RFCOMM Protocol TDI)
Intel(R) Ethernet Connection (2) I218-V
-fe80:0:0:0:4093:d169:536c:7c7c%eth7:fe80:0:0:0:4093:d169:536c:7c7c%eth7 - [B@16b4a017
Microsoft Wi-Fi Direct Virtual Adapter
-fe80:0:0:0:103e:cdf0:c0ac:1751%wlan1:fe80:0:0:0:103e:cdf0:c0ac:1751%wlan1 - [B@8807e25
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0000
VirtualBox Host-Only Ethernet Adapter-WFP Native MAC Layer LightWeight Filter-0000
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0001
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0002
VirtualBox Host-Only Ethernet Adapter-VirtualBox NDIS Light-Weight Filter-0000
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0003
VirtualBox Host-Only Ethernet Adapter-QoS Packet Scheduler-0000
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0004
VirtualBox Host-Only Ethernet Adapter-WFP 802.3 MAC Layer LightWeight Filter-0000
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0005
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0000
Intel(R) Ethernet Connection (2) I218-V-WFP Native MAC Layer LightWeight Filter-0000
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0001
Intel(R) Ethernet Connection (2) I218-V-Shrew Soft Lightweight Filter-0000
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0002
Intel(R) Ethernet Connection (2) I218-V-VirtualBox NDIS Light-Weight Filter-0000
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0003
Intel(R) Ethernet Connection (2) I218-V-QoS Packet Scheduler-0000
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0004
Intel(R) Ethernet Connection (2) I218-V-WFP 802.3 MAC Layer LightWeight Filter-0000
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0005
Broadcom 802.11ac Network Adapter-WFP Native MAC Layer LightWeight Filter-0000
Broadcom 802.11ac Network Adapter-Virtual WiFi Filter Driver-0000
Broadcom 802.11ac Network Adapter-Native WiFi Filter Driver-0000
Broadcom 802.11ac Network Adapter-HHD Software NDIS 6.0 Filter Driver-0003
Broadcom 802.11ac Network Adapter-Shrew Soft Lightweight Filter-0000
Broadcom 802.11ac Network Adapter-HHD Software NDIS 6.0 Filter Driver-0004
Broadcom 802.11ac Network Adapter-VirtualBox NDIS Light-Weight Filter-0000
Broadcom 802.11ac Network Adapter-HHD Software NDIS 6.0 Filter Driver-0005
Broadcom 802.11ac Network Adapter-QoS Packet Scheduler-0000
Broadcom 802.11ac Network Adapter-HHD Software NDIS 6.0 Filter Driver-0006
Broadcom 802.11ac Network Adapter-WFP 802.3 MAC Layer LightWeight Filter-0000
Broadcom 802.11ac Network Adapter-HHD Software NDIS 6.0 Filter Driver-0007
Microsoft Wi-Fi Direct Virtual Adapter-WFP Native MAC Layer LightWeight Filter-0000
Microsoft Wi-Fi Direct Virtual Adapter-Native WiFi Filter Driver-0000
Microsoft Wi-Fi Direct Virtual Adapter-HHD Software NDIS 6.0 Filter Driver-0002
Microsoft Wi-Fi Direct Virtual Adapter-Shrew Soft Lightweight Filter-0000
Microsoft Wi-Fi Direct Virtual Adapter-HHD Software NDIS 6.0 Filter Driver-0003
Microsoft Wi-Fi Direct Virtual Adapter-VirtualBox NDIS Light-Weight Filter-0000
Microsoft Wi-Fi Direct Virtual Adapter-HHD Software NDIS 6.0 Filter Driver-0004
Microsoft Wi-Fi Direct Virtual Adapter-QoS Packet Scheduler-0000
Microsoft Wi-Fi Direct Virtual Adapter-HHD Software NDIS 6.0 Filter Driver-0005
Microsoft Wi-Fi Direct Virtual Adapter-WFP 802.3 MAC Layer LightWeight Filter-0000
Microsoft Wi-Fi Direct Virtual Adapter-HHD Software NDIS 6.0 Filter Driver-0006
Для моего использования я настраиваю Upnp Server, это помогло понять "шаблон", который я искал. Некоторые возвращаемые объекты - это адаптеры Ethernet, сетевые адаптеры, виртуальные сетевые адаптеры, драйверы и клиентские адаптеры VPN. Не у всех тоже есть адрес. Так что вы захотите пропустить интерфейсные объекты, которые этого не делают.
Вы также можете добавить это в цикл для текущего NetworkInterface i
while(interfaces.hasMoreElements()){
Enumeration<InetAddress> addresses = i.getInetAddresses();
System.out.println(i.getDisplayName());
System.out.println("\t- name:" + i.getName());
System.out.println("\t- idx:" + i.getIndex());
System.out.println("\t- max trans unit (MTU):" + i.getMTU());
System.out.println("\t- is loopback:" + i.isLoopback());
System.out.println("\t- is PPP:" + i.isPointToPoint());
System.out.println("\t- isUp:" + i.isUp());
System.out.println("\t- isVirtual:" + i.isVirtual());
System.out.println("\t- supportsMulticast:" + i.supportsMulticast());
}
И вы увидите информацию в своем выводе так:
Software Loopback Interface 1
- name:lo
- idx:1
- max trans unit (MTU):-1
- is loopback:true
- is PPP:false
- isUp:true
- isVirtual:false
- supportsMulticast:true
-ADRESS: [127.0.0.1(VIKING-192.168.56.1)]127.0.0.1:127.0.0.1 - [B@19e1023e
-ADRESS: [0:0:0:0:0:0:0:1(VIKING-192.168.56.1)]0:0:0:0:0:0:0:1:0:0:0:0:0:0:0:1 - [B@7cef4e59
Broadcom 802.11ac Network Adapter
- name:wlan0
- idx:2
- max trans unit (MTU):1500
- is loopback:false
- is PPP:false
- isUp:true
- isVirtual:false
- supportsMulticast:true
-ADRESS: [VIKING.monkeybrains.net(VIKING-192.168.56.1)]VIKING.monkeybrains.net:192.168.1.142 - [B@64b8f8f4
-ADRESS: [fe80:0:0:0:81fa:31d:21c9:85cd%wlan0(VIKING-192.168.56.1)]fe80:0:0:0:81fa:31d:21c9:85cd%wlan0:fe80:0:0:0:81fa:31d:21c9:85cd%wlan0 - [B@2db0f6b2
Microsoft Kernel Debug Network Adapter
- name:eth0
- idx:3
- max trans unit (MTU):-1
- is loopback:false
- is PPP:false
- isUp:false
- isVirtual:false
- supportsMulticast:true
Используйте InetAddress.getLocalHost(), чтобы получить локальный адрес
import java.net.InetAddress;
try {
InetAddress addr = InetAddress.getLocalHost();
System.out.println(addr.getHostAddress());
} catch (UnknownHostException e) {
}
Ваш компьютер может иметь несколько
К сожалению, сетевой API в Java по-прежнему использует (старые) перечисления вместо итераторов и потоков, которым мы можем противостоять, обернув их как потоки. Итак, все, что нам нужно сделать, это
- поток по всем сетевым интерфейсам и их адресам , и
- отфильтровать местные
Код:
private Stream<InetAddress> getNonLocalIpAddresses() throws IOException {
return enumerationAsStream(NetworkInterface.getNetworkInterfaces())
.flatMap(networkInterface -> enumerationAsStream(networkInterface.getInetAddresses()))
.filter(inetAddress -> !inetAddress.isAnyLocalAddress())
.filter(inetAddress -> !inetAddress.isSiteLocalAddress())
.filter(inetAddress -> !inetAddress.isLoopbackAddress())
.filter(inetAddress -> !inetAddress.isLinkLocalAddress());
}
На моей машине это в настоящее время возвращает два адреса IPv6.
Чтобы получить первый из этих InetAdresses:
private String getMyIp() throws IOException {
return getNonLocalIpAddresses()
.map(InetAddress::getHostAddress)
.findFirst()
.orElseThrow(NoSuchElementException::new);
}
Метод, который оборачивает перечисления как потоки:
public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
new Iterator<>() {
public T next() { return e.nextElement(); }
public boolean hasNext() { return e.hasMoreElements(); }
}, Spliterator.ORDERED), false);
}
Довольно упрощенный подход, который, кажется, работает...
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();
}
Это получает IP-адрес вашей сети, если ваш компьютер является частью сети
try {
System.out.println(InetAddress.getLocalHost().getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
public class IpAddress {
NetworkInterface ifcfg;
Enumeration<InetAddress> addresses;
String address;
public String getIpAddress(String host) {
try {
ifcfg = NetworkInterface.getByName(host);
addresses = ifcfg.getInetAddresses();
while (addresses.hasMoreElements()) {
address = addresses.nextElement().toString();
address = address.replace("/", "");
}
} catch (Exception e) {
e.printStackTrace();
}
return ifcfg.toString();
}
}
Пример 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
}
}
}
}
}
Обычно, когда я пытаюсь найти свой публичный IP-адрес, такой как http://cmyip.com/ или https://www.iplocation.net/, я использую этот способ:
public static String myPublicIp() {
/*nslookup myip.opendns.com resolver1.opendns.com*/
String ipAdressDns = "";
try {
String command = "nslookup myip.opendns.com resolver1.opendns.com";
Process proc = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String s;
while ((s = stdInput.readLine()) != null) {
ipAdressDns += s + "\n";
}
} catch (IOException e) {
e.printStackTrace();
}
return ipAdressDns ;
}
Поскольку моя система (как и многие другие системы) имела различные сетевые интерфейсы.InetAddress.getLocalHost()
или Inet4Address.getLocalHost()
просто вернул тот, который мне не нравился. Поэтому мне пришлось использовать этот наивный подход.
InetAddress[] allAddresses = Inet4Address.getAllByName("YourComputerHostName");
InetAddress desiredAddress;
//In order to find the desired Ip to be routed by other modules (WiFi adapter)
for (InetAddress address :
allAddresses) {
if (address.getHostAddress().startsWith("192.168.2")) {
desiredAddress = address;
}
}
// Use the desired address for whatever purpose.
Просто будьте осторожны, так как при таком подходе я уже знал, что мой желаемый IP-адрес находится в 192.168.2
подсеть.
public static String getIpAddress() {
String ipAddress = null;
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
byte[] hardwareAddress = networkInterface.getHardwareAddress();
if (null == hardwareAddress || 0 == hardwareAddress.length || (0 == hardwareAddress[0] && 0 == hardwareAddress[1] && 0 == hardwareAddress[2])) continue;
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
if (inetAddresses.hasMoreElements()) ipAddress = inetAddresses.nextElement().toString();
break;
}
} catch (SocketException e) {
e.printStackTrace();
}
return ipAddress;
}