Recommended way to get hostname in Java - java

Which of the following is the best and most portable way to get the hostname of the current computer in Java?
Runtime.getRuntime().exec("hostname")
vs
InetAddress.getLocalHost().getHostName()

Strictly speaking - you have no choice but calling either hostname(1) or - on Unix gethostname(2). This is the name of your computer. Any attempt to determine the hostname by an IP address like this
InetAddress.getLocalHost().getHostName()
is bound to fail in some circumstances:
The IP address might not resolve into any name. Bad DNS setup, bad system setup or bad provider setup may be the reason for this.
A name in DNS can have many aliases called CNAMEs. These can only be resolved in one direction properly: name to address. The reverse direction is ambiguous. Which one is the "official" name?
A host can have many different IP addresses - and each address can have many different names. Two common cases are: One ethernet port has several "logical" IP addresses or the computer has several ethernet ports. It is configurable whether they share an IP or have different IPs. This is called "multihomed".
One Name in DNS can resolve to several IP Addresses. And not all of those addresses must be located on the same computer! (Usecase: A simple form of load-balancing)
Let's not even start talking about dynamic IP addresses.
Also don't confuse the name of an IP-address with the name of the host (hostname). A metaphor might make it clearer:
There is a large city (server) called "London". Inside the city walls much business happens. The city has several gates (IP addresses). Each gate has a name ("North Gate", "River Gate", "Southampton Gate"...) but the name of the gate is not the name of the city. Also you cannot deduce the name of the city by using the name of a gate - "North Gate" would catch half of the bigger cities and not just one city. However - a stranger (IP packet) walks along the river and asks a local: "I have a strange address: 'Rivergate, second left, third house'. Can you help me?" The local says: "Of course, you are on the right road, simply go ahead and you will arrive at your destination within half an hour."
This illustrates it pretty much I think.
The good news is: The real hostname is usually not necessary. In most cases any name which resolves into an IP address on this host will do. (The stranger might enter the city by Northgate, but helpful locals translate the "2nd left" part.)
In the remaining corner cases you must use the definitive source of this configuration setting - which is the C function gethostname(2). That function is also called by the program hostname.

InetAddress.getLocalHost().getHostName() is the more portable way.
exec("hostname") actually calls out to the operating system to execute the hostname command.
Here are a couple other related answers on SO:
Java current machine name and logged in user?
Get DNS name of local machine as seen by a remote machine
EDIT: You should take a look at A.H.'s answer or Arnout Engelen's answer for details on why this might not work as expected, depending on your situation. As an answer for this person who specifically requested portable, I still think getHostName() is fine, but they bring up some good points that should be considered.

As others have noted, getting the hostname based on DNS resolution is unreliable.
Since this question is unfortunately still relevant in 2018, I'd like to share with you my network-independent solution, with some test runs on different systems.
The following code tries to do the following:
On Windows
Read the COMPUTERNAME environment variable through System.getenv().
Execute hostname.exe and read the response
On Linux
Read the HOSTNAME environment variable through System.getenv()
Execute hostname and read the response
Read /etc/hostname (to do this I'm executing cat since the snippet already contains code to execute and read. Simply reading the file would be better, though).
The code:
public static void main(String[] args) throws IOException {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
System.out.println("Windows computer name through env:\"" + System.getenv("COMPUTERNAME") + "\"");
System.out.println("Windows computer name through exec:\"" + execReadToString("hostname") + "\"");
} else if (os.contains("nix") || os.contains("nux") || os.contains("mac os x")) {
System.out.println("Unix-like computer name through env:\"" + System.getenv("HOSTNAME") + "\"");
System.out.println("Unix-like computer name through exec:\"" + execReadToString("hostname") + "\"");
System.out.println("Unix-like computer name through /etc/hostname:\"" + execReadToString("cat /etc/hostname") + "\"");
}
}
public static String execReadToString(String execCommand) throws IOException {
try (Scanner s = new Scanner(Runtime.getRuntime().exec(execCommand).getInputStream()).useDelimiter("\\A")) {
return s.hasNext() ? s.next() : "";
}
}
Results for different operating systems:
macOS 10.13.2
Unix-like computer name through env:"null"
Unix-like computer name through exec:"machinename
"
Unix-like computer name through /etc/hostname:""
OpenSuse 13.1
Unix-like computer name through env:"machinename"
Unix-like computer name through exec:"machinename
"
Unix-like computer name through /etc/hostname:""
Ubuntu 14.04 LTS
This one is kinda strange since echo $HOSTNAME returns the correct hostname, but System.getenv("HOSTNAME") does not:
Unix-like computer name through env:"null"
Unix-like computer name through exec:"machinename
"
Unix-like computer name through /etc/hostname:"machinename
"
EDIT: According to legolas108, System.getenv("HOSTNAME") works on Ubuntu 14.04 if you run export HOSTNAME before executing the Java code.
Windows 7
Windows computer name through env:"MACHINENAME"
Windows computer name through exec:"machinename
"
Windows 10
Windows computer name through env:"MACHINENAME"
Windows computer name through exec:"machinename
"
The machine names have been replaced but I kept the capitalization and structure. Note the extra newline when executing hostname, you might have to take it into account in some cases.

InetAddress.getLocalHost().getHostName() is better (as explained by Nick), but still not very good
One host can be known under many different hostnames. Usually you'll be looking for the hostname your host has in a specific context.
For example, in a web application, you might be looking for the hostname used by whoever issued the request you're currently handling. How to best find that one depends on which framework you're using for your web application.
In some kind of other internet-facing service, you'll want the hostname your service is available through from the 'outside'. Due to proxies, firewalls etc this might not even be a hostname on the machine your service is installed on - you might try to come up with a reasonable default, but you should definitely make this configurable for whoever installs this.

Although this topic has already been answered there's more to say.
First of all: Clearly we need some definitions here. The InetAddress.getLocalHost().getHostName() gives you the name of the host as seen from a network perspective. The problems with this approach are well documented in the other answers: it often requires a DNS lookup, it's ambiguous if the host has multiple network interfaces and it just plain fails sometimes (see below).
But on any OS there's another name as well. A name of the host that gets defined very early in the boot process, long before the network is initialized. Windows refers to this as computername, Linux calls it kernel hostname and Solaris uses the word nodename. I like best the word computername, so I'll use that word from now on.
Finding the computername
On Linux/Unix the computername is what you get from the C function gethostname(), or hostname command from shell or HOSTNAME environment variable in Bash-like shells.
On Windows the computername is what you get from environment variable COMPUTERNAME or Win32 GetComputerName function.
Java has no way of obtaining what I've defined as 'computername'. Sure, there are workarounds as described in other answers, like for Windows calling System.getenv("COMPUTERNAME"), but on Unix/Linux there's no good workaround without resorting to JNI/JNA or Runtime.exec(). If you don't mind a JNI/JNA solution then there's gethostname4j which is dead simple and very easy to use.
Let's move on with two examples, one from Linux and one from Solaris, which demonstrate how you can easily get into a situation where you cannot obtain the computername using standard Java methods.
Linux example
On a newly created system, where the host during installation has been named as 'chicago', we now change the so-called kernel hostname:
$ hostnamectl --static set-hostname dallas
Now the kernel hostname is 'dallas', as evident from the hostname command:
$ hostname
dallas
But we still have
$ cat /etc/hosts
127.0.0.1 localhost
127.0.0.1 chicago
There's no misconfiguration in this. It just means the host's networked name (or rather the name of the loopback interface) is different from the host's computername.
Now, try executing InetAddress.getLocalHost().getHostName() and it will throw java.net.UnknownHostException. You are basically stuck. There's no way to retrieve neither the value 'dallas' nor the value 'chicago'.
Solaris example
The example below is based on Solaris 11.3.
The host has deliberately been configured so that the loopback name <> nodename.
In other words we have:
$ svccfg -s system/identity:node listprop config
...
...
config/loopback astring chicago
config/nodename astring dallas
and the contents of /etc/hosts :
:1 chicago localhost
127.0.0.1 chicago localhost loghost
and the result of the hostname command would be:
$ hostname
dallas
Just like in the Linux example a call to InetAddress.getLocalHost().getHostName() will fail with
java.net.UnknownHostException: dallas: dallas: node name or service name not known
Just like the Linux example you are now stuck. There's no way to retrieve neither the value 'dallas' nor the value 'chicago'.
When will you really struggle with this?
Very often you'll find that InetAddress.getLocalHost().getHostName() will indeed return a value which is equal to the computername. So there's no problem (except for the added overhead of name resolution).
The problem arises typically within PaaS environments where there's a difference between computername and the name of the loopback interface. For example people report problems in Amazon EC2.
Bug/RFE reports
A bit of searching reveals this RFE report : link1, link2. However, judging from the comments on that report the issue seems to have been largely misunderstood by the JDK team, so it is unlikely it will be addressed.
I like the comparison in the RFE to other programming languages.

Just one-liner ... cross platform (Windows-Linux-Unix-Mac(Unix)) [Always works, No DNS required]:
String hostname = new BufferedReader(
new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream()))
.readLine();
You're done !!

Environment variables may also provide a useful means -- COMPUTERNAME on Windows, HOSTNAME on most modern Unix/Linux shells.
See: https://stackoverflow.com/a/17956000/768795
I'm using these as "supplementary" methods to InetAddress.getLocalHost().getHostName(), since as several people point out, that function doesn't work in all environments.
Runtime.getRuntime().exec("hostname") is another possible supplement. At this stage, I haven't used it.
import java.net.InetAddress;
import java.net.UnknownHostException;
// try InetAddress.LocalHost first;
// NOTE -- InetAddress.getLocalHost().getHostName() will not work in certain environments.
try {
String result = InetAddress.getLocalHost().getHostName();
if (StringUtils.isNotEmpty( result))
return result;
} catch (UnknownHostException e) {
// failed; try alternate means.
}
// try environment properties.
//
String host = System.getenv("COMPUTERNAME");
if (host != null)
return host;
host = System.getenv("HOSTNAME");
if (host != null)
return host;
// undetermined.
return null;

The most portable way to get the hostname of the current computer in Java is as follows:
import java.net.InetAddress;
import java.net.UnknownHostException;
public class getHostName {
public static void main(String[] args) throws UnknownHostException {
InetAddress iAddress = InetAddress.getLocalHost();
String hostName = iAddress.getHostName();
//To get the Canonical host name
String canonicalHostName = iAddress.getCanonicalHostName();
System.out.println("HostName:" + hostName);
System.out.println("Canonical Host Name:" + canonicalHostName);
}
}

If you're not against using an external dependency from maven central, I wrote gethostname4j to solve this problem for myself. It just uses JNA to call libc's gethostname function (or gets the ComputerName on Windows) and returns it to you as a string.
https://github.com/mattsheppard/gethostname4j

hostName == null;
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
{
while (interfaces.hasMoreElements()) {
NetworkInterface nic = interfaces.nextElement();
Enumeration<InetAddress> addresses = nic.getInetAddresses();
while (hostName == null && addresses.hasMoreElements()) {
InetAddress address = addresses.nextElement();
if (!address.isLoopbackAddress()) {
hostName = address.getHostName();
}
}
}
}

Building off of Dan Ortega's answer, I created a generic executeCommand(String) method that takes a command as a paramater.
import java.io.*;
public class SystemUtil {
public static void main(String[] args) throws IOException {
System.out.println(retrieveHostName());
}
public static String retrieveHostName() throws IOException {
return executeCommand("hostname");
}
private static String executeCommand(String command) throws IOException {
return new BufferedReader(
new InputStreamReader(Runtime.getRuntime().exec(command).getInputStream()))
.readLine();
}
}

InetAddress.getLocalHost().getHostName() is the best way out of the two as this is the best abstraction at the developer level.

Related

InetAddress.getCanonicalHostName() returns IP instead of Hostname

I looked for how to do IP lookup in Java on Stack Overflow but the answers match what I am already doing and do not resolve my problem.
Here is my code:
public void printHostname( String ip ) {
System.out.println( InetAddresses.forString( ip ).getCanonicalHostName( ) );
}
InetAddresses is just a utility class from guava library to get a InetAdress.
The problem: This code works as expected with some IP adresses and not with some others.
A working example
For example, for IP 157.55.39.29, the output is:
msnbot-157-55-39-29.search.msn.com
This result seems correct according to Linux host command:
> host 157.55.39.29
29.39.55.157.in-addr.arpa domain name pointer msnbot-157-55-39-29.search.msn.com.
A not working example
For IP 123.125.71.75, the host command returns:
> host 123.125.71.75
75.71.125.123.in-addr.arpa domain name pointer baiduspider-123-125-71-75.crawl.baidu.com.
But the output of my Java code is:
123.125.71.75
whereas the expected output should be
baiduspider-123-125-71-75.crawl.baidu.com
The javadoc of getCanonicalHostName method says:
Returns:
the fully qualified domain name for this IP address, or if the operation is not allowed by the security check, the textual representation of the IP address.
but I’m pretty sure it's not really a problem with a security check... or I don't understand what is wrong.
Have you any suggestion to explain this behaviour? Do you have a workaround?
EDIT #1
When looking for a solution, I tried to step debug the implementation in JDK:
// first lookup the hostname
host = nameService.getHostByAddr(addr.getAddress());
/* check to see if calling code is allowed to know
* the hostname for this IP address, ie, connect to the host
*/
if (check) {
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
sec.checkConnect(host, -1);
}
}
/* now get all the IP addresses for this hostname,
* and make sure one of them matches the original IP
* address. We do this to try and prevent spoofing.
*/
InetAddress[] arr = InetAddress.getAllByName0(host, check);
In this code, variable host contains the correct value, but the last statement calling getAllByName0 throws an UnknownHostException which is handled by returning just the requested IP. The exception is thrown by internal method getAddressesFromNameServicewith message:
"java.net.UnknownHostException: baiduspider-123-125-71-75.crawl.baidu.com"
I don't know why.
Can I get the host variable value, bypassing the internal exception?
The problem lies in the fact that the java.net.InetAdress has a certain procedure against ip-spoofing.
It first resolves the name into (an) ip address(es). This works fine.
In your case the result are two IP adresses. InetAdress then checks back if (at least one of) these adresses resolve to the original input name.
If they do not, it just returns the original ip adress. The following picture shows the situation after the check for baiduspider-123-125-71-75.crawl.baidu.com
Note: The ip adresses resolved by getAllByName0 are the same as via nslookup, namely:
nslookup baiduspider-123-125-71-75.crawl.baidu.com
Server: 192.168.2.1
Address: 192.168.2.1#53
Non-authoritative answer:
Name: baiduspider-123-125-71-75.crawl.baidu.com
Address: 62.157.140.133
Name: baiduspider-123-125-71-75.crawl.baidu.com
Address: 80.156.86.78
A solution would be to use the dnsjava library. It skips the spoofing check and therefore works fine.
dnsjava example:
String addr = Address.getHostName(InetAddress.getByName("123.125.71.75"));
outputs just as expected baiduspider-123-125-71-75.crawl.baidu.com
Disclaimer: As i am a Java developer and not a security expert, i am not totally aware of the security implications of using a spoofed ip address.
I did not dig a lot into this so I don't know why it is happening, but some online tools (like this one) that checks the health of DNS servers indicates that they have some issues which may or may not be related.
As #jah said, Java tries to double check to see if the hostname has the ip it said it has. The exception is thrown on the native code while trying to do that. In fact, in my case, trying to verify on the command line, the nslookup fails to get the ip from the name, which indicates some configuration preventing this on the DNS Server (maybe on purpose? I'm no expert in DNS either).
When it works:
$ nslookup msnbot-157-55-39-29.search.msn.com
Server: 192.168.1.1
Address: 192.168.1.1#53
Non-authoritative answer:
Name: msnbot-157-55-39-29.search.msn.com
Address: 157.55.39.29
When it doesnt work:
$ nslookup baiduspider-123-125-71-75.crawl.baidu.com
Server: 192.168.1.1
Address: 192.168.1.1#53
** server can't find baiduspider-123-125-71-75.crawl.baidu.com: NXDOMAIN
When it works:
$ getent hosts msnbot-157-55-39-29.search.msn.com
157.55.39.29 msnbot-157-55-39-29.search.msn.com
When it doesn't:
$ getent hosts baiduspider-123-125-71-75.crawl.baidu.com
$
As an alternative, you can use a DNS Service Provider for JNDI. The documentation has an example, but I'll leave a working snippet for you to test:
String[] octets = "123.125.71.75".split("\\.");
String host = String.join(".", octets[3], octets[2], octets[1], octets[0], "in-addr.arpa");
Properties props = new Properties();
props.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
DirContext dirContext = new InitialDirContext(props);
Attributes attrs = dirContext.getAttributes(host, new String[] {"PTR"});
System.out.println(attrs.get("PTR").get());

Trying to get InetAddress.getLocalHost.getHostAddress (Java/Scala) to return external IP

So I'm having a problem with using InetAddress.getLocalHost.getHostAddress to get the external IP address of a given machine.
I'm actually doing this in Scala in a sense - the configuration file for Akka Remote Actors default uses InetAddress.getLocalHost.getHostAddress to get the IP address of the machine, which is what I want since I will be deploying the actors on several machines. However, it seems to be returning 127.0.0.1 instead of the external IP address I want (since the remote actors need to communicate back and forth across the netwrok).
The problem is that I can't use any of the methods I've found on Google to circumvent this since they all seem to involve adjusting the code itself, whereas here I don't really have any code to adjust, the DSL just automatically uses InetAddress.getLocalHost.getHostAddress.
I've read on a few threads from a Google search that you can circumvent this by editing your host file or something? How do I do this?
Thanks!
-kstruct
You may want to use NetworkInterface class.
In particular, use static getNetworkInterfaces method to enumerate all available network interfaces.
Check your /etc/hosts file. It should map 'localhost' to 127.0.0.1 and your real hostname to your real IP address, or one of them :-| Some Linux distributions get this wrong apparently.
i got a partial solution if getLocalHost doesn't works.
this solution have the problem that you must to know the name of your network interface in order to match the real one. Maybe you can improve this code removing "virtual" devices and something else.
This is scala code, but java code is very similar
def returnInterfaceAddress() : InetAddress = {
var myInetAddress = InetAddress.getLocalHost
val interfaces : util.Enumeration[NetworkInterface] = NetworkInterface.getNetworkInterfaces()
while(interfaces.hasMoreElements){
val inter = interfaces.nextElement()
if(inter.getDisplayName() == "Realtek PCIe GBE Family Controller"){
myInetAddress = inter.getInetAddresses().nextElement()
}
}
myInetAddress
}

How to figure out an IPv6 address (by name) of a host in my LAN

I have two computers plugged in the same router of a network which I know supports IPv6. Let's call them "PC-A" and "PC-B
I want "PC-A" to figure out "PC-B"s IPv6 address and vice-versa
The first thing I do is
setSystem.setProperty("java.net.preferIPv6Addresses", "true");
If I then say
InetAddress IPAddress = InetAddress.getLocalHost();
I can get my own address which will be in IpV6 format
However, neither of the following two statements gives me "PC-B"s IPv6 address:
Inet6Address IPAddress6 = (Inet6Address)InetAddress.getByName("PC-B");
InetAddress IPAddress = InetAddress.getByName("PC-B");
I also tried to import
import com.lavantech.net.dns.SimpleDNSLookup;
import com.lavantech.net.dns.DNSLookup
The first one I am using as:
SimpleDNSLookup d = new SimpleDNSLookup();
System.out.println(d.getInet6Address("PC-B"));
and the second one as:
DNSLookup dnsLookup = new DNSLookup("PC-B", DNSLookup.QTYPE_AAAA, DNSLookup.QCLASS_IN, 3000, null);
// Get all Address Records.
ResourceRecord[] ansRecords = dnsLookup.getAAAARecords();
System.out.println(ansRecords[0]);
none of which works.
I also tried to use the following
import org.xbill.DNS.*;
int type = Type.AAAA;
Name name = Name.fromString("PC-B");
Lookup lookup = new Lookup(name, type);
lookup.run();
int result = lookup.getResult();
Record[] answers = lookup.getAnswers();
System.out.println(answers[0]);
// (where, for brevity, i am skipping the parts where I check whether result == Lookup.SUCCESSFUL
Note that if I substitute "PC-B" for, say, "ipv6.google.com" I get all the desired results!
Also note that if I just use InetAddress and Type_A wherever applicable in the above approaches, my program returns "PC-B"s IPv4 address without problem.
What am I missing?
Any help is greatly appreciated!
Your question is -unfortunately- a yet unsolved network problem dealing with host discovery on a local subnet (regardless if that subnet has a router or not).
Your desired output is clearly an IPv6 address, but it is unclear what exactly your input is.
Let's focus on PC-B. How exactly do you identify PC-B? It clear that you call it "PC-B", but that name should be configured somewhere before your PC know that that's its name. Where exactly is that configured? Is that the hostname you set on PC-B itself, or is there a domain name server (DNS) where you have given that name? If it is the name in the DNS system, you can indeed query the DNS system for the AAAA record to get the IPv6 address, but you need the fully qualified domain name (FQDN). E.g. "PC-B.yourdomain.com" rather than just "PC-B".
If you know the MAC address of PC-B, you can use the neighbour discovery protocol (NDP) to find out the IP address of PC-B.
There are network protocols that allow PC-A and PC-B to announce their names themselves, once you configured them on the local machines. Such protocols are called "service discovery" protocols, and your options here are (1) multicast DNS (mDNS) and possibly DNS service discovery (DNS-SD) on top of that; or (2) Simple Service Discovery Protocol (SSDP) in UPnP on the other hand. The advantage is that some operating systems already implement this. E.g. if PC-B is a Mac OS X host, all you need to do is query DNS for "pc-b.local" to get the answer. Unfortunately, while implementations of mDNS exist for Linux (Avahi) and Windows (Bonjour), they're not installed by default. A third alternative is to write your own host discovery protocol, and have your hosts run that protocol.
Considerations are which platforms you want to support, if installing third-party software is an option, if the discovery needs to be secure (the above options are not, look into Secure Neighbour Discovery -SEND- if this is a concern), and what input you have in the first place (the hostname "PC-B", or the type of service that runs on PC-B, e.g. _http._tcp for a webserver).

Why isn't Java's InetAddress class resolving ipv6 addresses to their FQDN?

I'm trying to write a simple program using Java that, given an IP in either version 4 or 6 format, will return its FQDN. The following code works fine when given an ipv4 address, but will only return the given address when an ipv6 address is entered.
InetAddress inet;
try { inet = InetAddress.getByName(theIpAddress); }
catch(UnknownHostException e) { System.out.println("Unknown Host"); return; }
System.out.println(inet.getHostAddress(););
System.out.println(inet.getHostName(););
Whenever I enter an ipv6 getHostName() will only return the same ipv6, even when I know that the ipv6 will resolve to a FQDN. Also, if I enter an ipv6 host name, such as ipv6.google.com, in place of theIpAddress, the exception will occur.
I'm new to this stuff so would appreciate any assistance. Thanks.
The problem was actually the version of Java I was running. Updating Java to 1.6.23, from 1.6.21, allowed ipv6s to resolve to their FQDN.
I've done a quick investigation of what's going on with hostname <-> ipv6 resolution in java 8, Windows 7.
Looks like 'default' NameService does not work with ipv6 at all!
But! Java comes with another, JNDI based NameService implementation called 'dns,sun'.
So, if you enable it using either
-Dsun.net.spi.nameservice.provider.1=dns,sun
or
System.setProperty("sun.net.spi.nameservice.provider.1", "dns,sun");
you will get bidirectional ip <-> hostname resolution for v4 and v6 addresses like this
InetAddress.getAllByName(...)
address.getHostName()
More info about java ipv6 you can find here http://docs.oracle.com/javase/8/docs/technotes/guides/net/ipv6_guide/
Try inet.getCanonicalHostName(); which "Gets the fully qualified domain name for this IP address."
If you construct the InetAddress using InetAddress.getByName(), getHostName() will return what you constructed it with. getCanonicalHostName() forces a reverse name lookup.
Using java.net.InetAddress it is not possible to have ipv6 and ipv4 name resolution etc. The bunch of static methods like getByName etc delegate the lookup to instance of Inet4(or 6)AddressImpl that does
public native InetAddress[] lookupAllHostAddr(String hostname) throws UnknownHostException;
Now the fun is a) all these are private/package local so there is not way to inject the impl classes to the InetAddress class b) Inet4(or 6)AddressImpl classes are themselves package local . So there is no way to say , do a ipv4 or ipv6 lookup/name resolution on the fly. I do not get the way all extension points were blocked for these classes making them of really very limited use and flexibility.
The real black-magic happens here , where InetAddress class statically initializes the impls, on what does outcome of method isIPv6Supported() dependent ?? My Linux setup supports ipv6 , i can do dns lookups for ipv6 hostnames like ipv6.google.com.
Will appreciate if anybody can point me to the direction of a good net library in java for ipv4/v6 utilities like lookup etc.
class InetAddressImplFactory {
static InetAddressImpl create() {
Object o;
if (isIPv6Supported()) {
o = InetAddress.loadImpl("Inet6AddressImpl");
} else {
o = InetAddress.loadImpl("Inet4AddressImpl");
}
return (InetAddressImpl)o;
}
static native boolean isIPv6Supported();
}

After Port Forwarding, how to get my external IP in Java?

I set up a static IP and did port forwarding on my notebook, and now I have a static IP address, but it's relatively static, every time I re-start the machine, I get another address, and since I have a "static" IP I can now do Paypal IPN messaging. But how can I get this static IP from my Java program ? One way I can think of is to visit : http://portforward.com/ and on that page it tells me what my external IP is, so I can extract it with Java code, is there any other way that I can do in my Java code to get this info ?
The best solution is probably dynamic DNS. Essentially, you run a program on your computer (or router) that notifies a DNS server when your IP changes. Then, you can just tell PayPal the domain name.
There is a public service you can call with your script to retrieve your external IP address. Bear in mind they have changed the link location once. If you control your own server, you should probably write your own PHP script to simply return the address of the caller to the script.
http://www.whatismyip.com/faq/automation.asp - follow the developers link they provide
import java.net.*;
import java.io.*;
URL myExternalIP = new URL("PUT THE LINK HERE");
BufferedReader in = new BufferedReader(new InputStreamReader(
myExternalIP.openStream()));
String ip = in.readLine(); //you get the IP as a String
System.out.println(ip);
Your own server script is a simple one-liner. Create a file called whatismyip.php and here's the content.
<? echo $_SERVER['REMOTE_ADDR']?>
I see three ways of doing this:
As you discovered, querying an external server what IP you're apparently connecting from. This is simple but you require such a service to be available and, usually, that no transparent proxy messes with your results.
IGD, a sub-protocol of UPnP can give you the result very easily if your port forwarding devices supports it (many do). Google "IGD JAVA" for libraries and samples.
Register for a dynamic DNS service and then lookup your own DNS name.
You can use the NetworkInterface class:
Enumeration<NetworkInterface> ifcs = NetworkInterface.getNetworkInterfaces();
while(ifcs.hasMoreElements()){
NetworkInterface ifc = ifcs.nextElement();
System.out.println("Adresses of: "+ifc.getDisplayName());
Enumeration<InetAddress> adresses = ifc.getInetAddresses();
while(adresses.hasMoreElements()){
System.out.println(adresses.nextElement().getHostAddress());
}
}
This snippet will show you all of the interfaces and the IPs bound to them. You will need to look through the list to find the appropriate interface (see also NetworkInterface.getByName(String name)) And then look at the addresses for that interface. Once you have found the appropriate InetAdress you can use that to get the string or byte representation.

Categories

Resources