How come InetAddress.getByName("1.2") is valid ip address? - java

public class InetAddresTest {
public static void main(String ... agrs) {
try {
InetAddress inet = InetAddress.getByName("1.2");
System.out.println("Good ip address");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
BTW the InetAddress produced ip address comes back as "1.0.0.2" . I could not find a reasonable answer from the javadoc of InetAddress. Can you someone explain this behaviour ?

From the Javadoc (Linked in "Textual representation of IP addresses" in the Javadoc for InetAddress ):
When a two part address is supplied, the last part is interpreted as a 24-bit quantity and placed in the right most three bytes of the network address. This makes the two part address format convenient for specifying Class A network addresses as net.host.
Edit to add: In case the 24bit part is confusing to you:
2 in 24bit would look like: 00000000 00000000 00000010
Which is then mapped to the right 3 octets in the IPv4 address as: .0.0.2
One More: As CoolBeans mentions in the comments to your question, the InetAddressValidator from Apache commons would do the trick. That being said, if you just want to validate IP addresses and not have an external dependency, you can use Regular Expressions to check IP addresses as well

Related

InetAddress.getAllByName() throws UnknownHostException

As part of an ongoing saga to get my app approved by the Apple review team, I have come up against another road block.
As the title suggests, when calling InetAddress.getAllByName("https://artatlas.io") an UnknownHostException is thrown. This only happens during their testing process. When I test my app on my local NAT64 network (as suggested by Apple); the error never occurs, and the app works as intended.
The code I am running:
System.setProperty("java.net.preferIPv6Addresses", "true");
System.setProperty("networkaddress.cache.negative.ttl", "0");
InetAddress[] addrs;
try {
addrs = InetAddress.getAllByName("https://artatlas.io");
String addresses = "";
for(InetAddress addr: addrs){
addresses += addr + "\n";
}
System.out.println("Addresses: " + addresses + "\n");
} catch (IOException e1) {
e1.printStackTrace();
}
What I've discovered is, anything I append with "https://" seems to return the same, single IP address:
Addresses: https://artatlas.io/122.150.5.20
Addresses: https://google.com/122.150.5.20
Addresses: https://www.google.com/122.150.5.20
I could just get rid of the https, but then I'm concerned my later use of a HttpsURLConnection will fail (my connection MUST be https)
testUrl = new URL("https://artatlas.io");
testConn = (HttpsURLConnection) testUrl.openConnection();
I know that a HttpsURLConnection uses an InetAddress instance to form its connection, so the question is what process does it use to parse the URL string, does it remove the protocol? What's the correct approach here?
The hostname shouldn't include a protocol. The host is the same, no matter what protocol you intend to use with it. Whether the later HTTPS connection fails or not, InetAddress.getAllByName() is unrelated to it (it doesn't and can't guarantee success or failure).
You're dealing with DNS only at this point, so it's just foo.com or 123.45.67.89 or an IPv6 address.

Why do we have to use InetSocketAddress to enter our port number for using ServerSocketChannel

why do we have to create an object of InetSocketAddress?
but for ServerSocket we just use int to enter port number
Example:
try(
ServerSocketChannel listener = ServerSocketChannel.open();
ServerSocket serverSocket = listener.socket()
){
serverSocket.bind(new InetSocketAddress(2266));
//we can't use serverSocket.bind(2266);
}catch (IOException e){
e.printStackTrace();
}
Your question is somewhat unclear.
ServerSocket#bind() establishes the local end of the connection. If your system has more than one network adapter and/or more than one IP address, AND you wanted to connect the socket using a specific local adapter or IP address, then you would provide a complete InetSocketAddress(host,port) with both host and port, where the host part was one of your local IP addresses.
In the default case where you have only one IP address, or have more than one but don't care which one is used as the source, you can omit the host and just specify the port, as in your example.
The API is defined this way. A TCP connection is symmetrical, and is defined by its two endpoints. An endpoint is a pair (host,port). This applies to BOTH ends of the connection. Thus the bind() call takes an InetSocketAddress parameter. For convenience, InetSocketAddress will assume the default host that specifies "use any available interface" if you provide only a port.
The API designers could have added a bind(int port) method to build the InetSocketAddress(port) behind the scenes, but clearly didn't feel it was necessary.
InetSocketAddress creates a socket address where the IP address is the wildcard address and the port number a specified value
wildcard is special IP address which can be used for binding. If you don't want to listen "everything" but maybe spesific IPs, say, 5.5.5.5 for example, you will be binded to that IP address but not others.
But without the IP part to it means any IP will be listened so pretty much no difference for this particular usage.

What does InetAddress.isSiteLocalAddress() actually mean?

Here is some code to determine the local host name that is supposed to work on a multi-homed box:
/**
* Work out the first local host name by iterating the network interfaces
*
* #return
* #throws SocketException
*/
private String findFirstLocalHostName() throws SocketException {
Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
while (ifaces.hasMoreElements()) {
NetworkInterface iface = ifaces.nextElement();
Enumeration<InetAddress> addresses = iface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress add = addresses.nextElement();
if (!add.isLoopbackAddress() && add.isSiteLocalAddress()) {
return add.getHostName();
}
}
}
throw new RuntimeException("Failed to determine local hostname");
}
Does the call to isSiteLocalAddress introduce a bug? I can't find any useful information about this method, but I have a feeling that it relates to IP v 6 only and is deprecated.
The method is definitely not deprecated and it's definitely not just used in IPv6.
In IPv4 there are 3 network address ranges that are defined for site-local addresses: 10/8, 172.16/12 and 192.168/16.
Reading Inet4Address.isSiteLocalAddress() shows that addresses from exactly those 3 networks will return true on those methods.
IPv6 has a similar concept, here these addresses are called unique local addresses.
Effectively this tells you if the address you have is definitely not a public one (note that even if this method returns false, the address might still not be public).
Looking at the implementation...
For an Inet4Address, it checks to see if it's one of the RFC1918 "unrouteable" addresses: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.
For an Inet6Address, it checks the first two octets to see if it's a real "site local" address.
'Site local' is a deprecated name for private IP space. (Some nuances, but basically right.) See RFC 1918.
I just came across what I believe is a similar problem: trying to determine what IPv6 I should use for LAN comuncation:
IMHO, Inet6Address.isSiteLocalAddress() is useless. Given that the 0xFEC0 prefix has been depricated by RFC 3879 as #tigz mentioned. I have yet to see any device (android, win, osx) actually have a 0xFEC0 (with limited testing)
//from java.net.Inet6Address (1.8.0_45)
boolean isSiteLocalAddress() {
return ((ipaddress[0] & 0xff) == 0xfe
&& (ipaddress[1] & 0xc0) == 0xc0);
}
0xFE80 address although not supposed be used for traffic (from my understanding and reading (www.cisco.com)) did work for LAN communication with my single router (ping6, curl, http).
My Global Unicast (which is just another name for public IP) 2601::/20 from Comcast worked for my LAN communication. So I would say that this is the correct address to use.
Prefix table: www.iana.org
As far as I know the isSiteLocalAddress method is not deprecated.
isSiteLocalAddress - Explanation
indicating if the InetAddress is a site local address; or false if address is not a site local unicast address.
The InetAddress even have two direct subclasses;
Inet4Address and
Inet6Address
The best bet is to read the JavaDocs.
Which version of the JDK are you using?

Different Outputs_networking

import java.net.*;
class check {
public static void main(String args[])throws Exception {
InetAddress address=InetAddress.getLocalHost();
System.out.println(address);
}
}
Now the first output is when i am connected to internet and second output is when i am not connected to internet.
What type of ip address is the second one? (the one encapsulated in InetAddress with internet not working)
Please help me in this.
127.0.0.1 is the loopback address. It's always present on your computer. When you don't have an externally accessible IP assigned to your machine, that's your local address.
127.0.0.1 is the canonical loopback address, in short, it's an always-available address of your own machine.
Actually, just googling this address brings relevant info instantly.
127.0.0.1 is the default loopback address of any machine when its no assigned particular ip

How do you specify a port range for Java sockets?

In Java you can give the number zero as a single parameter for the Socket or DatagramSocket constructor. Java binds that Socket to a free port then. Is it possible to limit the port lookup to a specific range?
Hrm, after reading the docs, I don't think you can. You can either bind to any port, then rebind if it is not acceptable, or repeatedly bind to a port in your range until you succeed. The second method is going to be most "efficient".
I am uneasy about this answer, because it is... inelegant, yet I really can't find anything else either :/
Binding the socket to any free port is (usually) a feature of the operating system's socket support; it's not specific to java. Solaris, for example, supports adjusting the ephemeral port range through the ndd command. But only root can adjust the range, and it affects the entire system, not just your program.
If the regular ephemeral binding behavior doesn't suit your needs, you'll probably have to write your own using Socket.bind().
Here's the code you need:
public static Socket getListeningSocket() {
for ( int port = MIN_PORT ; port <= MAX_PORT ; port++ )
{
try {
ServerSocket s = new ServerSocket( port );
return s; // no exception means port was available
} catch (IOException e) {
// try the next port
}
}
return null; // port not found, perhaps throw exception?
}
You might glance at the java code that implements the function you are using. Most of the java libraries are written in Java, so you might just see what you need in there.
Assuming #Kenster was right and it's a system operation, you may have to simply iterate over ports trying to bind to each one or test it. Although it's a little painful, it shouldn't be more than a few lines of code.

Categories

Resources