Networking in Java programming includes the ability to locate and identify resources and communicate over TCP and UDP connections. First you need to identify the resource with a name like www.ibm.com, then open a connection to that resource, and finally send packets between yourself and the other end of the connection. Additional tasks may be involved for the sake of security, but the overall process stays the same. With the Java platform, the classes to support these operations are found in the java.net package. From the early days of Java programming to the present, most of these operations haven't changed much. With Merlin, though, some of these basic operations have improved to support new and worthwhile features. In this article, we'll look at five such features: IPv6 support, URIs, network interfaces, unbound sockets, and secure sockets.
First let's look at the new support for the next generation Internet Protocol version 6 (IPv6) addressing architecture. With the help of two new subclasses of InetAddress -- Inet4Address and Inet6Address -- you'll be able to connect to TCP- and UDP-based applications. Inet4Address supports the older (and typically only) IP addressing style supported on most machines, in the form of 127.0.0.1 for localhost. The new addressing scheme, defined in RFC2373 (see Resources), provides a colon-separated format, where 0:0:0:0:0:0:0:1 is the loopback address equivalent to 127.0.0.1. The new classes allow applications to support one or both of the addressing schemes.
Support for IPv6 is dependent on the underlying platform supporting it, which is available for Solaris 8 and up and Linux 2.1.2 and up (RedHat 6.1+), but not Microsoft Windows (the Microsoft implementation for Window 2000 is a limited implementation). Expect a Windows version of J2SE 1.4 that supports IPv6 at a later time.
Getting to know uniform resource identifiers
The java.net package now includes a uniform resource identifier (URI) class. Think of a URI as a uniform resource locator (URL) without a protocol handler behind it. Typically, URLs look like http://www.ibm.com. For the Java language runtime to understand the URL, it needs to know what to do with something that begins with http:. Previously, if you came up with a new protocol (for instance, something like jdbc:database), if there was no protocol handler, you couldn't treat the jdbc:database string as a URL. Instead, you had to treat it strictly as a string, which is what JDBC now does.
The typical form of a URI is [scheme:][//authority][path][?query][#fragment], where the authority is typically just a host name. However, it can also include user login information and a port: [userInfo@]host[:port]. The URI class itself provides a series of getter methods to get at the specific pieces of the URI. You should use this class where you previously passed around a string that looked like a URL, but was only intended to describe the URL -- not to be used as one.
Listing network connections with NetworkInterface
Have you ever wanted to know which networking interfaces were available, but didn't know how to ask without reverting to native code? Typically, most machines connected to the Internet have two connections: a local loop to themselves and a connection to their local service provider. Some machines, however, are multi-homed. They have multiple networking cards, each with a separate connection to the Internet and each with their own name and address. With the new NetworkInterface interface, you can specify which networking card is used when sending outgoing multicast datagrams, or just check to see if the network connection is currently up. Listing 1 demonstrates the class usage:
Listing 1. Listing network interfaces
import java.net.*;
import java.util.Enumeration;
public class Nets {
public static void main(String args[]) throws SocketException {
Enumeration enum = NetworkInterface.getNetworkInterfaces();
while (enum.hasMoreElements()) {
NetworkInterface net = (NetworkInterface)enum.nextElement();
System.out.println(
"Names: " + net.getName() + " / " + net.getDisplayName());
Enumeration enum2 = net.getInetAddresses();
while (enum2.hasMoreElements()) {
InetAddress address = (InetAddress)enum2.nextElement();
System.out.println("\tAddress: " + address.getHostAddress());
}
}
}
}
|
Your results when running this program are bound to differ. Listing 2 includes a sample of the output you would expect to see:
Listing 2. Sample results for Listing 1
Names: lo / MS TCP Loopback interface
Address: 127.0.0.1
Names: eth0 / 3Com EtherLink PCI
Address: 192.168.0.109
|
Support for unconnected and unbound sockets
Typically, operations such as reading and writing across sockets are blocking operations. Until the operation completes, the calling thread can't continue. With the help of the new I/O (NIO) classes of Merlin, the networking classes can now be non-blocking. In either case (blocking or non-blocking), the new InetSocketAddress and SocketAddress classes allow you to open a connection to a host and port, then set some options for the connection before actually connecting to the host. Listing 3 shows the basic sequence of operations:
Listing 3. Connecting to a host and port
String hostname = ...; int port = ...; SocketAddress socketAddress = new InetSocketAddress(host, port); SocketChannel channel = SocketChannel.open(); channel.configureBlocking(false); channel.connect(socketAddress); |
Look for more information on the NIO packages in next month's column.
Connecting with secure sockets
A new package in Merlin is javax.net.ssl. This package offers secure communications using the Java secure socket extension (JSSE), more commonly known as secure sockets layer (SSL) support for https URLs. You no longer have to get a standard extension library for SSL support -- it now comes with the core libraries. By asking for an SSL socket from SSLSocketFactory, you automatically have a secure connection, assuming the server you're connected to supports the feature. After getting the socket, you don't have to do anything special -- it communicates in the exact same way as a normal socket.
In Listing 4, we use SSL to connect to a user-specified site, or Verisign, and fetch the entry page for the site. Feel free to save the output to a file to view it.
Listing 4. Connecting over a secure socket
import java.io.*;
import java.net.*;
import javax.net.*;
import javax.net.ssl.*;
public class SslSample {
static final int HTTPS_PORT = 443;
public static void main(String args[]) throws IOException {
String hostname;
// If host not provided, connect to Verisign
if (args.length == 0) {
hostname = "www.verisign.com";
} else {
hostname = args[0];
}
// Get socket factory
SocketFactory factory = SSLSocketFactory.getDefault();
// Get socket from factory
Socket socket = factory.createSocket(hostname, HTTPS_PORT);
// Send request
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
// Setup command
String command = "GET / HTTP/1.0\r\n\r\n";
pw.print(command);
pw.flush();
// Get response
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
pw.close();
br.close();
socket.close();
}
}
|
There is also an HttpsURLConnection class to use like jave.net.URLConnection.
Not all the networking enhancements are through new classes (and packages). Many of the existing classes have been enhanced, too. Some features are mostly behind the scenes, like the improved FTP protocol handler. Its capabilities now more closely match those of RFC1738 and RFC959 (see Resources), including support for passive mode. In addition, the URLEncoder and URLDecoder classes support working with programmer-specified character sets for encoding and decoding. The HTTP digest authentication support has also been improved, and URLConnection header processing has been enhanced to support getting and adding headers directly.
Merlin adds many features to standard Java programming. Some features have been around for a while, but are finally being incorporated into the standard release. Some capabilities are new, while others are updates to existing features. As the use of Java technology grows, it's becoming more difficult to keep up with its expanding list of capabilities. Sometimes you need to dig around to find the gems, but keep looking -- they're there.
- Read the complete Magic with Merlin column series.
- Read RFC2373 to learn about the IP Version 6 Addressing Architecture.
- Learn about IPv6 addresses in "Writing a simple IPv6 program" (developerWorks, September 2001).
- Find out about all the J2SE 1.4 Networking Enhancements discussed in this article.
- Learn more about Java Secure Socket Extension (JSSE) from its reference guide.
- Greg Travis offers some hands-on training with JSSE in his tutorial, "Using JSSE for secure socket communication" (developerWorks, April 2002).
- Learn how to get Java applications to network on small devices in "Networking with J2ME" (developerWorks, September 2002).
- Learn about URLs in RFC1738.
- Learn about FTP in RFC959.
- Find hundreds of articles about every aspect of Java programming in the
developerWorks Java technology zone.

John Zukowski conducts strategic Java software consulting with JZ Ventures, Inc. and serves as the resident guru for a number of jGuru's community-driven Java FAQs. His latest books are Learn Java with JBuilder 6 from Apress and Mastering Java 2: J2SE 1.4 from Sybex. You can reach him at jaz@zukowski.net.