Question simple et pourtant vaste que voilà . Comment obtenir le nom et l’adresse ip de la machine sur laquelle tourne votre application java? Sous son aspect simple dans l’énoncé se cachent en fait une multitude de possibilités. Comment définissez vous « l’adresse ip » de la machine? Une IPv4 ou une IPv6? Une ip locale ou une ip telle que vue par vos clients?
Tout d’abord, il faut décider de ce que vous désirez comme adresse. Une machine peut avoir plusieurs ips différentes. C’est le ca, par exemple, des serveurs, mais même une petite machine de bureau, comme nous allons le voir, peut foisonner, à votre insu, d’adresses IPs.
locale ou wan?
Que ce soit votre machine de bureau, votre PC à domicile, la caisse enregistreuse électronique du magasin où vous allez faire vos courses, de plus en plus d’ordinateurs sont relié à un réseau. Pour des raisons de coût et de limitations de l’IPv4, la plupart de ces réseaux sont des réseaux locaux avec des adresses ip locales. Il existe alors souvent dans ces réseaux, pour sortir, un routeur dont le travail est de transformer vos paquets sortant afin de leur donner à tous une adresse dite publique (et non plus locale), que nous appellerons ip wan.
Parmi les grandes différences qui existent entre votre ip locale et votre ip wan se situe le noeud de notre problème. L’ip wan est sous contrôle du routeur alors que l’ip locale est sous votre contrôle. Le routeur utilise une technique qu’on appelle le NAT pour changer vos paquets à destination du tout grand internet. Cette technique est entièrement gérée par le routeur. Quoi que vous fassiez, vous n’avez aucun contrôle dessus et tout se passe comme si l’ip n’avais pas été changée.
Des techniques existent pour obtenir son IP wan, mais elles nécessitent un serveur pair extérieur qui vous informe de sous quelle ip vous apparaissez. Ou alors l’utilisation de certaines commandes relative au protocol upnp, si votre routeur gère ce protocole. Ce document se concentre uniquement sur l’ip locale.
IPv4 ou IPv6?
Autre question subsidiaire à vous poser. Désirez vous obtenir votre adresse IPv4 ou IPv6? Sur certains systèmes, vous n’aurez pas le choix, mais sur d’autres, un même nom d’hôte peut posséder une adresse IPv4 et un équivalent IPv6. Laquelle désirez vous conserver? Si votre code est susceptible de tourner encore dans quelques années, il serait judicieux de donner la priorité à l’IPv6, celle-ci étant amenée dans un futur indéterminé à remplacer l’IPv4.
avec ou sans le localhost?
Tout PC relié à un réseau possède au moins une adresse, le localhost. En IPv4, cette adresse est 127.0.0.1, en IPv6, c’est 0:0:0:0:0:0:0:1. Attendez vous à la voir ressortir souvent, Si vous utilisez ce code, en java, c’est elle qui risque de ressortir (en réalité ça dépend de l’OS sur lequel tourne le code et de sa configuration):
java.net.InetAddress.getLocalHost().getHostAddress()
petit code
Pour finir, voilà un joli code qui liste toutes les adresses locales de la machine ainsi que l’information sur la localité de l’adresse, si il s’agit d’une IPv6 et d’un IPv4 et si il s’agit d’une adresse de type localhost. Bref, tout ce donc vous avez besoin pour décider laquelle vous prenez.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.Enumeration;
import java.net.NetworkInterface;
//.....
Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
while (e.hasMoreElements()){
Enumeration<InetAddress> i = e.nextElement().getInetAddresses();
while (i.hasMoreElements()){
InetAddress a = i.nextElement();
System.out.println(a.getHostName()+" -> "+a.getHostAddress()+
"\n\t isloopback? "+a.isLoopbackAddress()+
"\n\t isSiteLocalAddress? "+a.isSiteLocalAddress()+
"\n\t isIPV6? "+(a instanceof Inet6Address)
);
}
System.out.println("---------------");
}
comme vous pouvez le constater, ce code fait appel à NetworkInterface.getNetworkInterfaces() pour obtenir la liste des interfaces réseau dont dispose votre machine. A partir de là , il est possible, pour chaque interface, d’obtenir la listes des adresses IPs qui lui sont liées et de filtrer sur base de différents critères. La détection de l’IPv6 se fait via la détection de la classe implémentant InetAddress.
Voici quelques exemples de réponse sortie avec ce code (ips partiellement cachées):
- sur une machine de bureau
fe80:0:0:0:21e:xxxx:xxxx:xxxx%2 -> fe80:0:0:0:21e:xxxx:xxxx:xxxx%2 isloopback? false isSiteLocalAddress? false isIPV6? true xxx.yyy.be -> 192.168.xxx.xxx isloopback? false isSiteLocalAddress? true isIPV6? false --------------- localhost -> 0:0:0:0:0:0:0:1%1 isloopback? true isSiteLocalAddress? false isIPV6? true localhost -> 127.0.0.1 isloopback? true isSiteLocalAddress? false isIPV6? false ---------------
- sur un serveur
aaa.bbb.be -> 193.190.xxx.yyy isloopback? false isSiteLocalAddress? false isIPV6? false zzzz -> 192.168.xxx.yyy isloopback? false isSiteLocalAddress? true isIPV6? false --------------- 0:0:0:0:0:0:0:1%1 -> 0:0:0:0:0:0:0:1%1 isloopback? true isSiteLocalAddress? false isIPV6? true localhost -> 127.0.0.1 isloopback? true isSiteLocalAddress? false isIPV6? false ---------------
- et un autre serveur
localhost -> 127.0.0.1 isloopback? true isSiteLocalAddress? false isIPV6? false --------------- 10.xxx.yyy.zzz -> 10.xxx.yyy.zzz isloopback? false isSiteLocalAddress? true isIPV6? false --------------- aaa.bbb.be -> 193.190.xxx.yyy isloopback? false isSiteLocalAddress? false isIPV6? false ccc.bbb.be -> 193.190.xxx.zzz isloopback? false isSiteLocalAddress? false isIPV6? false ---------------
Pas que je sache, mais si tu t’oriente vers les protocole upnp (pour gérer l’ip distante), je sais que le logiciel Azureus, en java, implémente au moins en partie ce protocole pour gérer ses ports. Il y a peut-être quelque chose à récupérer de ce coté là ….
Pour la gestion de base, je ne vois pas pourquoi jakarta fournirait une librairie, les données étant présentes dans l’api standard de java, ça n’a jamais été la vocation de jakarta de réinventer la roue de ce coté là .
David,
Très sympathique ton billet.
Sais-tu s’il existe d’autres API qui font a peu près la même chose (du côté Apache …) ?
Mickael