Monday, December 20, 2010

Network Interface Parameters

You can access network parameters about a network interface beyond the name and IP addresses assigned to it
You can discover if a network interface is “up” (that is, running) with the isUP() method. The following methods indicate the network interface type:
  • isLoopback() indicates if the network interface is a loopback interface.
  • isPointToPoint() indicates if the interface is a point-to-point interface.
  • isVirtual() indicates if the interface is a virtual interface.
The supportsMulticast() method indicates whether the network interface supports multicasting. The getHardwareAddress() method returns the network interface's physical hardware address, usually called MAC address, when it is available. The getMTU() method returns the Maximum Transmission Unit (MTU), which is the largest packet size.
The following example expands on the example in Listing Network Interface Addresses by adding the additional network parameters described on this page:
import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;

public class ListNetsEx
{
    public static void main(String args[]) throws SocketException {
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface netint : Collections.list(nets))
            displayInterfaceInformation(netint);
    }

    static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
        out.printf("Display name: %s\n", netint.getDisplayName());
        out.printf("Name: %s\n", netint.getName());
        Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
        
        for (InetAddress inetAddress : Collections.list(inetAddresses)) {
            out.printf("InetAddress: %s\n", inetAddress);
        }
       
        out.printf("Up? %s\n", netint.isUp());
        out.printf("Loopback? %s\n", netint.isLoopback());
        out.printf("PointToPoint? %s\n", netint.isPointToPoint());
        out.printf("Supports multicast? %s\n", netint.supportsMulticast());
        out.printf("Virtual? %s\n", netint.isVirtual());
        out.printf("Hardware address: %s\n",
                    Arrays.toString(netint.getHardwareAddress()));
        out.printf("MTU: %s\n", netint.getMTU());
        
        out.printf("\n");

     }
}  

Sunday, December 19, 2010

What Is a Socket?

A socket is one end-point of a two-way communication link between two programs running on the network. Socket classes are used to represent the connection between a client program and a server program. The java.net package provides two classes--Socket and ServerSocket--that implement the client side of the connection and the server side of the connection, respectively.

All About Sockets

URLs and URLConnections provide a relatively high-level mechanism for accessing resources on the Internet. Sometimes your programs require lower-level network communication, for example, when you want to write a client-server application.
In client-server applications, the server provides some service, such as processing database queries or sending out current stock prices. The client uses the service provided by the server, either displaying database query results to the user or making stock purchase recommendations to an investor. The communication that occurs between the client and the server must be reliable. That is, no data can be dropped and it must arrive on the client side in the same order in which the server sent it.
TCP provides a reliable, point-to-point communication channel that client-server applications on the Internet use to communicate with each other. To communicate over TCP, a client program and a server program establish a connection to one another. Each program binds a socket to its end of the connection. To communicate, the client and the server each reads from and writes to the socket bound to the connection.

Reading from and Writing to a URLConnection

Reading from a URLConnection

The following program performs the same function as the URLReader program shown in Reading Directly from a URL. However, rather than getting an input stream directly from the URL, this program explicitly retrieves a URLConnection object and gets an input stream from the connection. The connection is opened implicitly by calling getInputStream. Then, like URLReader, this program creates a BufferedReader on the input stream and reads from it. The bold statements highlight the differences between this example and the previous
import java.net.*;
import java.io.*;

public class URLConnectionReader {
    public static void main(String[] args) throws Exception {
        URL yahoo = new URL("http://www.yahoo.com/");
        URLConnection yc = yahoo.openConnection();
        BufferedReader in = new BufferedReader(
                                new InputStreamReader(
                                yc.getInputStream()));
        String inputLine;

        while ((inputLine = in.readLine()) != null) 
            System.out.println(inputLine);
        in.close();
    }
}
The output from this program is identical to the output from the program that opens a stream directly from the URL. You can use either way to read from a URL. However, reading from a URLConnection instead of reading directly from a URL might be more useful. This is because you can use the URLConnection object for other tasks (like writing to the URL) at the same time. Again, if the program hangs or you see an error message, you may have to set the proxy host so that the program can find the Yahoo server.

Writing to a URLConnection

Many HTML pages contain forms-- text fields and other GUI objects that let you enter data to send to the server. After you type in the required information and initiate the query by clicking a button, your Web browser writes the data to the URL over the network. At the other end the server receives the data, processes it, and then sends you a response, usually in the form of a new HTML page. Many of these HTML forms use the HTTP POST METHOD to send data to the server. Thus writing to a URL is often called posting to a URL. The server recognizes the POST request and reads the data sent from the client.
For a Java program to interact with a server-side process it simply must be able to write to a URL, thus providing data to the server. It can do this by following these steps:
  1. Create a URL.
  2. Retrieve the URLConnection object.
  3. Set output capability on the URLConnection.
  4. Open a connection to the resource.
  5. Get an output stream from the connection.
  6. Write to the output stream.
  7. Close the output stream.
Here is a small servlet named ReverseServlet ( or if you prefer a cgi-bin script ). You can use this servlet to test the following example program.
The servlet running in a container reads from its InputStream, reverses the string, and writes it to its OutputStream. The servlet requires input of the form string=string_to_reverse, where string_to_reverse is the string whose characters you want displayed in reverse order.
Here's an example program that runs the ReverseServlet over the network through a URLConnection:
import java.io.*;
import java.net.*;

public class Reverse {
    public static void main(String[] args) throws Exception {

 if (args.length != 2) {
     System.err.println("Usage:  java Reverse " +
                               "http://<location of your servlet/script>" + 
                               " string_to_reverse");
     System.exit(1);
 }

 String stringToReverse = URLEncoder.encode(args[1], "UTF-8");

 URL url = new URL(args[0]);
 URLConnection connection = url.openConnection();
 connection.setDoOutput(true);

 OutputStreamWriter out = new OutputStreamWriter(
                              connection.getOutputStream());
 out.write("string=" + stringToReverse);
 out.close();

 BufferedReader in = new BufferedReader(
    new InputStreamReader(
    connection.getInputStream()));
    
 String decodedString;

 while ((decodedString = in.readLine()) != null) {
     System.out.println(decodedString);
 }
 in.close();
    }
}
Let's examine the program and see how it works. First, the program processes its command-line arguments:
if (args.length != 2) {
    System.err.println("Usage:  java Reverse " +
                        "http://<location of your servlet/script>" + 
                 " string_to_reverse");
    System.exit(1);
} 

String stringToReverse = URLEncoder.encode(args[1], "UTF-8");
These statements ensure that the user provides two and only two command-line arguments to the program. The command-line arguments are the location of the ReverseServlet and the string that will be reversed. It may contain spaces or other non-alphanumeric characters. These characters must be encoded because the string is processed on its way to the server. The URLEncoder class methods encode the characters. Next, the program creates the URL object, and sets the connection so that it can write to it:
URL url = new URL(args[0]);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
The program then creates an output stream on the connection and opens an OutputStreamWriter on it:
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
If the URL does not support output, getOutputStream method throws an UnknownServiceException. If the URL does support output, then this method returns an output stream that is connected to the input stream of the URL on the server side--the client's output is the server's input. Next, the program writes the required information to the output stream and closes the stream:
out.write("string=" + stringToReverse);
out.close();
This code writes to the output stream using the write method. So you can see that writing data to a URL is as easy as writing data to a stream. The data written to the output stream on the client side is the input for the servlet on the server side. The Reverse program constructs the input in the form required by the script by prepending string= to the encoded string to be reversed. The serlvet reads the information you write, performs a reverse operation on the string value, and then sends this back to you. You now need to read the string the server has sent back. The Reverse program does it like this:
BufferedReader in = new BufferedReader(
                    new InputStreamReader(
                    connection.getInputStream()));
    
String decodedString;

while ((decodedString = in.readLine()) != null) {
    System.out.println(decodedString);
}
in.close();
If your ReverseServlet is located at http://foobar.com/servlet/ReverseServlet, then when you run the Reverse program using
http://foobar.com/servlet/ReverseServlet "Reverse Me"
as the argument (including the double quote marks), you should see this output:
Reverse Me
 reversed is: 
eM esreveR

Connecting to a URL

After you've successfully created a URL object, you can call the URL object's openConnection method to get a URLConnection object, or one of its protocol specific subclasses, e.g. java.net.HttpURLConnection You can use this URLConnection object to setup parameters and general request properties that you may need before connecting. Connection to the remote object represented by the URL is only initiated when the URLConnection.connect method is called. When you do this you are initializing a communication link between your Java program and the URL over the network. For example, you can open a connection to the Yahoo site with the following code:
try {
    URL yahoo = new URL("http://www.yahoo.com/");
    URLConnection yahooConnection = yahoo.openConnection();
    yahooConnection.connect();

} catch (MalformedURLException e) {     // new URL() failed
    . . .
} catch (IOException e) {               // openConnection() failed
    . . .
}
A new URLConnection object is created every time by calling the openConnection method of the protocol handler for this URL. You are not always required to explicitly call the connect method to initiate the connection. Operations that depend on being connected, like getInputStream, getOutputStream, etc, will implicitly perform the connection, if necessary.
Now that you've successfully connected to your URL, you can use the URLConnection object to perform actions such as reading from or writing to the connection. The next section shows you how.

Reading Directly from a URL

After you've successfully created a URL, you can call the URL's openStream() method to get a stream from which you can read the contents of the URL. The openStream() method returns a java.io.InputStream object, so reading from a URL is as easy as reading from an input stream. The following small Java program uses openStream() to get an input stream on the URL http://www.yahoo.com/. It then opens a BufferedReader on the input stream and reads from the BufferedReader thereby reading from the URL. Everything read is copied to the standard output stream:
import java.net.*;
import java.io.*;

public class URLReader {
    public static void main(String[] args) throws Exception {
 URL yahoo = new URL("http://www.yahoo.com/");
 BufferedReader in = new BufferedReader(
    new InputStreamReader(
    yahoo.openStream()));

 String inputLine;

 while ((inputLine = in.readLine()) != null)
     System.out.println(inputLine);

 in.close();
    }
}
When you run the program, you should see, scrolling by in your command window, the HTML commands and textual content from the HTML file located at http://www.yahoo.com/. Alternatively, the program might hang or you might see an exception stack trace. If either of the latter two events occurs, you may have to set the proxy host so that the program can find the Yahoo server.

Parsing a URL

The URL class provides several methods that let you query URL objects. You can get the protocol, authority, host name, port number, path, query, filename, and reference from a URL using these accessor methods:
getProtocol
Returns the protocol identifier component of the URL.
getAuthority
Returns the authority component of the URL.
getHost
Returns the host name component of the URL.
getPort
Returns the port number component of the URL. The getPort method returns an integer that is the port number. If the port is not set, getPort returns -1.
getPath
Returns the path component of this URL.
getQuery
Returns the query component of this URL.
getFile
Returns the filename component of the URL. The getFile method returns the same as getPath, plus the concatenation of the value of getQuery, if any.
getRef
Returns the reference component of the URL.