官术网_书友最值得收藏!

Network addressing concepts

There are different types of network addresses. An address serves to identify a node in a network. For example, the Internetwork Packet Exchange (IPX) protocol was an earlier protocol that was used to access nodes on a network. The X.25 is a protocol suite for Wide Area Network (WAN) packet switching. A MAC address provides a unique identifier for network interfaces at the physical network level. However, our primary interests are IP addresses.

URL/URI/URN

These terms are used to refer to the name and location of an Internet resource. A URI identifies the name of a resource, such as a website, or a file on the Internet. It may contain the name of a resource and its location.

A URL specifies where a resource is located, and how to retrieve it. A protocol forms the first part of the URL, and specifies how data is retrieved. URLs always contain protocol, such as HTTP, or FTP. For example, the following two URLs use different protocols. The first one uses the HTTPS protocol, and the second one uses the FTP protocol:

https://www.packtpub.com/

ftp://speedtest.tele2.net/

Java provides classes to support URIs and URLs. The discussion of these classes begins in the next section. Here, we will discuss URNs in more depth.

A URN identifies the resource but not its location. A URN is like a city's name, while a URL is similar to a city's latitude and longitude. When a resource, such as web page, or file, is moved, the URL for the resource is no longer correct. The URL will need to be updated wherever it is used. A URN specifies the name of a resource but not its location. Some other entity, when supplied with a URN, will return its location. URNs are not used that extensively.

The syntax of a URN is shown next. The <NID> element is a namespace identifier and <NSS> is a namespace-specific string:

<URN> ::= "urn:" <NID> ":" <NSS>

For example, the following is a URN specifying as part of a SOAP message to qualify its namespace:

<?xml version='1.0'?>
<SOAP:Envelope
  xmlns:SOAP='urn:schemas-xmlsoap-org:soap.v1'>
 <SOAP:Body>
  ...
    xmlns:i='urn:gargantuan-com:IShop'>
   ...
 </SOAP:Body>
</SOAP:Envelope>

It is used in other places, such as to identify books using their ISBN. Entering the following URL in a browser will bring up a reference to an EJB book:

https://books.google.com/books?isbn=9781849682381

The syntax of a URN depends on the namespace. The IANA is responsible for the allocation of many Internet resources, including URN namespaces. URNs are still an active area of research. URLs and URNs are both URIs.

Using the URI class

The general syntax of a URI consists of a scheme and a scheme-specific-part:

[scheme:] scheme-specific-part

There are many schemes that are used with a URI, including:

  • file: This is used for files systems
  • FTP: This is File Transfer Protocol
  • HTTP: This is commonly used for websites
  • mailto: This is used as part of a mail service
  • urn: This is used to identify a resource by name

The scheme-specific-part varies by the scheme that is used. URIs can be categorized as absolute or relative, or as opaque or hierarchical. These distinctions are not of immediate interest to us here, though Java provides methods to determine whether a URI falls into one of these categories.

Creating URI instances

A URI can be created for different schemes using several constructor variations. The simplest way of creating a URI is to use a string argument specifying the URI, as shown here:

    URI uri = new 
        URI("https://www.packtpub.com/books/content/support");

The next URI uses a fragment to access a subsection of the Wikipedia article dealing with the normalization of a URL:

    uri = new URI("https://en.wikipedia.org/wiki/"
        + "URL_normalization#Normalization_process");

We can also use the following version of the constructor to specify the scheme, host, path, and fragment of the URI:

    uri = new 
        URI("https","en.wikipedia.org","/wiki/URL_normalization",
        "Normalization_process");

These latter two URIs are identical.

Splitting apart a URI

Java uses the URI class to represent a URI, and it possesses several methods to extract parts of a URI. The more useful methods are listed in the following table:

There are also several "raw" methods, such as getRawPath, or getRawFragment, which return versions of a path or fragment, respectively. This includes special characters, such as the question mark, or character sequences beginning with an asterisk. There are several character categories defining these characters and their use, as documented at http://docs.oracle.com/javase/8/docs/api/java/net/URI.html.

We have developed the following helper method that is used to display URI characteristics:

    private static void displayURI(URI uri) {
        System.out.println("getAuthority: " + uri.getAuthority());
        System.out.println("getScheme: " + uri.getScheme());
        System.out.println("getSchemeSpecificPart: " 
            + uri.getSchemeSpecificPart());
        System.out.println("getHost: " + uri.getHost());
        System.out.println("getPath: " + uri.getPath());
        System.out.println("getQuery: " + uri.getQuery());
        System.out.println("getFragment: " + uri.getFragment());
        System.out.println("getUserInfo: " + uri.getUserInfo());
        System.out.println("normalize: " + uri.normalize());
    }

The next code sequence creates a URI instance for the Packtpub website and then calls the displayURI method:

    try {
        URI uri = new 
            URI("https://www.packtpub.com/books/content/support");
        displayURI(uri);
    } catch (URISyntaxException ex) {
        // Handle exceptions
    }

The output of this sequence is as follows:

getAuthority: www.packtpub.com

getScheme: https

getSchemeSpecificPart: //www.packtpub.com/books/content/support

getHost: www.packtpub.com

getPath: /books/content/support

getQuery: null

getFragment: null

getUserInfo: null

normalize: https://www.packtpub.com/books/content/support

http://www.packtpub.com

More often, these methods are used to extract relevant information for additional processing.

Using the URL class

One of the easiest ways to connect to a site and retrieve data is through the URL class. All that you need to provide is the URL for the site and the details of the protocol. An instance of the InetAddress class will hold an IP address and possibly the hostname for the address.

The URLConnection class was introduced in Chapter 1, Getting Started with Network Programming. It can also be used to provide access to an Internet resource represented by a URL. We will discuss this class and its use in Chapter 4, Client/Server Development.

Creating URL instances

There are several ways of creating a URL instance. The easiest is to simply provide the URL of the site as the argument of the class' constructor. This is illustrated here where a URL instance for the Packtpub website is created:

    URL url = new URL("http://www.packtpub.com");

A URL requires a protocol to be specified. For example, the following attempt to create a URL will result in a java.net.MalformedURLException: no protocol: www.packtpub.com error message:

    url = new URL("www.packtpub.com"); 

There are several constructor variations. The following two variations will create the same URL. The second one uses parameters for the protocol, host, port number, and file:

    url = new URL("http://pluto.jhuapl.edu/");
    url = new URL("http", "pluto.jhuapl.edu", 80, 
        "News-Center/index.php");

Splitting apart a URL

It can be useful to know more about a URL. We may not even know what URL we are using if the user entered one that we need to process. There are several methods that support splitting a URL into its components, as summarized in the following table:

We will use the following method to illustrate the methods in the preceding table:

    private static void displayURL(URL url) {
        System.out.println("URL: " + url);
        System.out.printf("  Protocol: %-32s  Host: %-32s\n",
            url.getProtocol(),url.getHost());
        System.out.printf("      Port: %-32d  Path: %-32s\n", 
            url.getPort(),url.getPath());
        System.out.printf(" Reference: %-32s  File: %-32s\n",
            url.getRef(),url.getFile());
        System.out.printf(" Authority: %-32s Query: %-32s\n", 
            url.getAuthority(),url.getQuery());
        System.out.println(" User Info: " + url.getUserInfo());
    }

The following output demonstrates the output when several URL are used as arguments to this method.

URL: http://www.packpub.com
  Protocol: http                              Host: www.packpub.com                 
      Port: -1                                Path:                                 
 Reference: null                              File:                                 
 Authority: www.packpub.com                  Query: null                            
 User Info: null

URL: http://pluto.jhuapl.edu/
  Protocol: http                              Host: pluto.jhuapl.edu                
      Port: -1                                Path: /                               
 Reference: null                              File: /                               
 Authority: pluto.jhuapl.edu                 Query: null                            
 User Info: null

URL: http://pluto.jhuapl.edu:80News-Center/index.php
  Protocol: http                              Host: pluto.jhuapl.edu                
      Port: 80                                Path: News-Center/index.php           
 Reference: null                              File: News-Center/index.php           
 Authority: pluto.jhuapl.edu:80              Query: null                            
 User Info: null

URL: https://en.wikipedia.org/wiki/Uniform_resource_locator#Syntax
  Protocol: https                             Host: en.wikipedia.org                
      Port: -1                                Path: /wiki/Uniform_resource_locator  
 Reference: Syntax                            File: /wiki/Uniform_resource_locator  
 Authority: en.wikipedia.org                 Query: null                            
 User Info: null

URL: https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=url+syntax
  Protocol: https                             Host: www.google.com                  
      Port: -1                                Path: /webhp                          
 Reference: q=url+syntax                      File: /webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8
 Authority: www.google.com                   Query: sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8
 User Info: null

URL: https://www.packtpub.com/books/content/support
  Protocol: https                             Host: www.packtpub.com                
      Port: -1                                Path: /books/content/support          
 Reference: null                              File: /books/content/support          
 Authority: www.packtpub.com                 Query: null                            
 User Info: null

The URL class also supports opening connections and IO streams. We demonstrated the openConnection method in Chapter 1, Getting Started with Network Programming. The getContent method returns the data referenced by the URL. For example, the following applies the method against the Packtpub URL:

    url = new URL("http://www.packtpub.com");
    System.out.println("getContent: " + url.getContent());

The output is as follows:

sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@5c647e05

This suggests that we need to use an input stream to process the resource. The type of data depends on the URL. This topic is explored with the URLConnection class that is discussed in Chapter 4, Client/Server Development.

IP addresses and the InetAddress class

An IP address is a numerical value that is used to identify a node, such as a computer, printer, scanner, or a similar device. It is used for network interface addressing, and location addressing. The address, unique in its context, identifies the device. At the same time it constitutes a location in the network. A name designates an entity, such as unusually routed though one or more nodes.

Obtaining information about an address

The InetAddress class represents an IP address. The IP protocol is a low-level protocol used by the UDP and TCP protocols. An IP address is either a 32-bit or a 128-bit unsigned number that is assigned to a device.

IP addresses have a long history and use two major versions: IPv4 and IPv6. The number 5 was assigned to the Internet Stream Protocol. This was an experimental protocol, but it was never actually referred to as version IPv5 and was not intended for general use.

The InetAddress class' getAllByName method will return the IP address for a given URL. In the following example, the addresses associated with www.google.com are displayed:

    InetAddress names[] = 
        InetAddress.getAllByName("www.google.com");
    for(InetAddress element : names) {
        System.out.println(element);
    }

One possible output is as follows. The output will vary depending on the location and time because many web sites have multiple IP addresses assigned to them. In this case, it uses both IPv4 and IPv6 addresses:

www.google.com/74.125.21.105

www.google.com/74.125.21.103

www.google.com/74.125.21.147

www.google.com/74.125.21.104

www.google.com/74.125.21.99

www.google.com/74.125.21.106

www.google.com/2607:f8b0:4002:c06:0:0:0:69

The InetAddress class possesses several methods to provide access to an IP address. We will introduce them as they become relevant. We start with methods to return its canonical hostname, hostname, and host address. They are used in the following helper method:

    private static void displayInetAddressInformation(
            InetAddress address) {
        System.out.println(address);
        System.out.println("CanonicalHostName: " +
            address.getCanonicalHostName());
        System.out.println("HostName: " + address.getHostName());
        System.out.println("HostAddress: " + 
            address.getHostAddress());
    }

The canonical hostname is a Fully Qualified Domain Name (FQDN). As the term implies, it is the full name of the host, including the top-level domain. The values returned by these methods depend on several factors, including the DNS server. The system provides information regarding entities on the network.

The following sequence uses the display method for the Packtpub website:

    InetAddress address = 
        InetAddress.getByName("www.packtpub.com");
    displayInetAddressInformation(address);

You will get an output that is similar to the following one:

www.packtpub.com/83.166.169.231

CanonicalHostName: 83.166.169.231

HostAddress: 83.166.169.231

HostName: www.packtpub.com

The InetAddress class' toString method returned the hostname, followed by the forward slash and then the host address. The getCanonicalHostName method, in this case, returned the host address, which is not the FQDN. The method will do its best to return the name but may not be able to depending on the machine's configuration.

Address scoping issues

The scope of an IP address refers to the uniqueness of an IP address. Within a local network, such as those used in many homes and offices, the address may be local to that network. There are three types of scopes:

  • Link-local: This is used within a single local subnet that is not connected to the Internet. No routers are present. Allocation of link-local addresses is done automatically when the computer does not have a static IP-address and cannot find a DHCP server.
  • Site-local: This is used when the address does not require a global prefix and is unique within a site. It cannot be reached directly from the Internet and requires a mapping service such as NAT.
  • Global: As its name implies, the address is unique throughout the Internet.

There are also private addresses that are discussed in the Private addresses in IPv4 and Private addresses in IPv6 sections. The InetAddress class supports several methods to identify the type of address being used. Most of these methods are self-explanatory, as found in the following table where MC is an abbreviation for multicast:

The addresses types and ranges used are summarized in the following table for IPv4 and IPv6:

Testing reachability

The InetAddress class' isReachable method will attempt to determine whether an address can be found. If it can, the method returns true. The following example demonstrates this method. The getAllByName method returns an array of an InetAddress instance available for the URL. The isReachable method uses an integer argument to specify how long to wait in milliseconds at a maximum before deciding that the address is not reachable:

    String URLAddress = "www. packtpub.com";
    InetAddress[] addresses = 
        InetAddress.getAllByName(URLAddress);
    for (InetAddress inetAddress : addresses) {
        try {
            if (inetAddress.isReachable(10000)) {
                System.out.println(inetAddress + " is reachable");
            } else {
                System.out.println(inetAddress + 
                    " is not reachable");
            }
        } catch (IOException ex) {
            // Handle exceptions
        }
    }

The URL www.packtpub.com was reachable, as shown here:

www.packtpub.com/83.166.169.231 is reachable

However, www.google.com was not:

www.google.com/173.194.121.52 is not reachable

www.google.com/173.194.121.51 is not reachable

www.google.com/2607:f8b0:4004:809:0:0:0:1014 is not reachable

Your results may vary. The isReachable method will do its best to determine whether an address is reachable or not. However, its success depends on more than simply whether the address exists. Reasons for failure can include: the server may be down, network response time was too long, or a firewall may be blocking a site. The operating system and JVM settings can also impact how well the method works.

An alternative to this method is to use the RunTime class' exec method to execute a ping command against the URL. However, this is not portable and may still suffer from some of the same factors that impact the success of the isReachable method.

Introducing the Inet4Address

This address consists of 32 bits, permitting up to 4,294,967,296 (232) addresses. The human readable form of the address consists of four decimal numbers (8 bits), each ranging from 0 to 255. Some of the addresses have been reserved for private networks and multicast addresses.

Early on in the use of IPv4, the first octet (8 bit unit) represented a network number (also called the network prefix or network block), and the remaining bits represented a rest field (host identifier). Later, three classes were used to partition the addresses: A, B, and C. These system have largely fallen into disuse and have been replaced by the Classless Inter-Domain Routing (CIDR). This routing approach allocates addresses on bit boundaries, providing more flexibility. This scheme is called classless in contrast to the earlier class-full systems. In IPv6, 64-bit network identifiers are used.

Private addresses in IPv4

Private networks do not necessarily need global access to the Internet. This results in a series of addresses being allocated for these private networks.

You may recognize that the last set of addresses is used by the home network. A private network often interfaces with the Internet using NAT. This technique maps a local IP address to one accessible on the Internet. It was originally introduced to ease the IPv4 address shortage.

IPv4 address types

There are three address types that are supported in IPv4:

  • Unicast: This address is used to identify a single node in a network
  • Multicast: This address corresponds to a group of network interfaces. Members will join a group and a message is sent to all members of the group
  • Broadcast: This will send a message to all network interfaces on a subnet

The Inet4Address class supports the IPv4 protocol. We will examine this class in more depth next.

The Inet4Address class

The Inet4Address class is derived from the InetAddress class. As a derived class, it does not override many of the InetAddress class' methods. For example, to obtain an InetAddress instance, we can use the getByName method of either class, as shown here:

    Inet4Address address;
    address = (Inet4Address) 
       InetAddress.getByName("www.google.com");
    address = (Inet4Address) 
        Inet4Address.getByName("www.google.com");

In either case, the address needs to be cast because the base class method is used in either case. The Inet4Address class does not add any new methods above and beyond that of the InetAddress class.

Special IPv4 addresses

There are several special IPv4 addresses, including these two:

  • 0.0.0.0: This is called an unspecified IPv4 address (wildcard address) and is normally used when a network interface does not have a IP address and is attempting to obtain one using DHCP.
  • 127.0.0.1: This is known as the loopback address. It provides a convenient way to send oneself a message, often for testing purposes.

The isAnyLocalAddress method will return true if the address is a wildcard address. This method is demonstrated here, where it returns true:

    address = (Inet4Address) Inet4Address.getByName("0.0.0.0");
    System.out.println(address.isAnyLocalAddress());

The isLoopbackAddress method is shown next and will return true:

    address = (Inet4Address) Inet4Address.getByName("127.0.0.1");
    System.out.println(address.isLoopbackAddress());

We will use this frequently to test servers in subsequent chapters.

In addition to these, other special addresses include those used for protocol assignments, IPv6 to IPv4 relay, and testing purposes. More details about these and other special addresses can be found at https://en.wikipedia.org/wiki/IPv4#Special-use_addresses.

Introducing the Inet6Address class

IPv6 addresses use 128 bits (16 octets). This permits up to 2128 addresses. An IPv6 address is written as a series of eight groups, with 4 hexadecimal numbers each, separated by colons. The digits are case insensitive. For example, the IPv6 address for www.google.com is as follows:

2607:f8b0:4002:0c08:0000:0000:0000:0067

An IPv6 address can be simplified in several ways. Leading zeroes in a group can be removed. The previous example can be rewritten as:

2607:f8b0:4002:c08:0:0:0:67

Consecutive groups of zeroes can be replaced with ::, as shown here:

2607:f8b0:4002:c08::67

IPv6 supports three addressing types:

  • Unicast: This specifies a single network interface.
  • Anycast: This type of address is assigned to a group of interfaces. When a packet is sent to this group, only one member of the group receives the packet, often the one that is closest.
  • Multicast: This sends a packet to all members of a group.

This protocol does not support broadcast addressing. There is much more to IPv6 than an increase in network size. It includes several improvements, such as easier administration, more efficient routing capabilities, simple header formats, and the elimination of the need for NAT.

Private addresses in IPv6

Private address space is available in IPv6. Originally, it used site-local addresses using a block with a prefix of fec0::/10. However, this has been dropped due to problems with its definition, and it was replaced with Unique Local (UL) addresses using the address block fc00::/7.

These addresses can be generated by anyone and do not need to be coordinated. However, they are not necessarily globally unique. Other private networks can use the same addresses. They cannot be assigned using a global DNS server and are only routable in the local address space.

The Inet6Address class

In general, using the Inet6Address class is not necessary unless you are developing an IPv6-only application. Most networking operations are handled transparently. The Inet6Address class is derived from the InetAddress class. The Inet6Address class's getByName method uses its base class, the InetAddrress class's getAllByName method, to return the first address that it finds, as shown next. This might not be an IPv6 address:

    public static InetAddress getByName(String host)
        throws UnknownHostException {
        return InetAddress.getAllByName(host)[0];
    }

Note

For some of these examples to work correctly, your router may need to be configured to support an IPv6 Internet connection.

The Inet6Address class added only one method above and beyond that of the InetAddress class. This is the isIPv4CompatibleAddress method that is discussed in the Using IPv4-compatible IPv6 addresses section.

Special IPv6 addresses

There is a block of addresses consisting of 64 network prefixes: 2001:0000::/29 through 2001:01f8::/29. These are used for special needs. Three have been assigned by IANA:

  • 2001::/32: This is the teredo tunneling, which is a transition technology from IPv4
  • 2001:2::/48: This is used for benchmarking purposes
  • 2001:20::/28: This is used for cryptographic hash identifiers

Most developers will not need to work with these addresses.

Testing for the IP address type

Normally, we are not concerned with whether the IP address is IPv4 or IPv6. The differences between the two are hidden beneath the various protocol levels. When you do need to know the difference, then you can use either of the two approaches. The getAddress method returns a byte array. You check the size of the byte array to determine if it is IPv4 or IPv6. Or you can use the instanceOf method. These two approaches are shown here:

    byte buffer[] = address.getAddress();
    if(buffer.length <= 4) {
        System.out.println("IPv4 Address");
    } else {
        System.out.println("IPv6 Address");
    }
    if(address instanceof Inet4Address) {
        System.out.println("IPv4 Address");
    } else {
        System.out.println("IPv6 Address");
    }

Using IPv4-compatible IPv6 addresses

The dotted quad notation is a way of expressing an IPv4 address using IPv6. The ::ffff: prefix is placed in front of either the IPv4 address or its equivalent in hexadecimal. For example, the hexadecimal equivalent of the IPv4 address 74.125.21.105 is 4a7d1569. Both represent a 32 bit quantity. Thus, any of the following three addresses represent the same website:

    address = InetAddress.getByName("74.125.21.105");
    address = InetAddress.getByName("::ffff:74.125.21.105");
    address = InetAddress.getByName("::ffff:4a7d:1569");

If we used these addresses with the displayInetAddressInformation method, the output will be identical, as shown here:

/74.125.21.105

CanonicalHostName: yv-in-f105.1e100.net

HostName: yv-in-f105.1e100.net

HostAddress: 74.125.21.105

CanonicalHostName: 83.166.169.231

These are referred to as IPv4-compatible IPv6 addresses.

The Inet6Address class possesses an isIPv4CompatibleAddress method. The method returns true if the address is merely an IPv4 address that is placed inside of an IPv6 address. When this happens, all but the last four bytes are zero.

The following example illustrates how this method can be used. Each address associated with www.google.com is tested to determine whether it is an IPv4 or IPv6 address. If it is an IPv6 address, then the method is applied to it:

    try {
        InetAddress names[] = 
            InetAddress.getAllByName("www.google.com");
        for (InetAddress address : names) {
            if ((address instanceof Inet6Address) && 
                       ((Inet6Address) address)
                           .isIPv4CompatibleAddress()) {
                System.out.println(address
                        + " is IPv4 Compatible Address");
            } else {
                System.out.println(address
                        + " is not a IPv4 Compatible Address");
            }
        }
    } catch (UnknownHostException ex) {
        // Handle exceptions
    }

The output depends on the servers available. The following is one possible output:

www.google.com/173.194.46.48 is not a IPv4 Compatible Address

www.google.com/173.194.46.51 is not a IPv4 Compatible Address

www.google.com/173.194.46.49 is not a IPv4 Compatible Address

www.google.com/173.194.46.52 is not a IPv4 Compatible Address

www.google.com/173.194.46.50 is not a IPv4 Compatible Address

www.google.com/2607:f8b0:4009:80b:0:0:0:2004 is not a IPv4 Compatible Address

An alternative Java 8 solution is as follows:

    names = InetAddress.getAllByName("www.google.com");
    Arrays.stream(names)
            .map(address -> {
                if ((address instanceof Inet6Address) && 
                        ((Inet6Address) address)
                            .isIPv4CompatibleAddress()) {
                    return address + 
                        " is IPv4 Compatible Address";
                } else {
                    return address + 
                        " is not IPv4 Compatible Address";
                }
            })
            .forEach(result -> System.out.println(result));
主站蜘蛛池模板: 普安县| 永定县| 格尔木市| 延安市| 旬邑县| 溧阳市| 临湘市| 平塘县| 呼伦贝尔市| 华阴市| 临沂市| 白水县| 阿拉善右旗| 琼海市| 神木县| 阜城县| 溧水县| 石城县| 友谊县| 灌南县| 霍邱县| 灌南县| 泽州县| 香港 | 永靖县| 肇源县| 神农架林区| 灵台县| 甘肃省| 林州市| 孙吴县| 班玛县| 理塘县| 永修县| 抚宁县| 三门县| 江达县| 瑞昌市| 日喀则市| 罗定市| 隆化县|