HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

The Internet has been very popular in the past few years. With its popularity still growing, increased demand for Internet network software has grown as well. One of the greatest advantages to developing Internet software with Java is in its robust networking support built into the core language. The java.net package provides us with classes representing URLs, URL connections and sockets. Combined with the java.io package, we can quite easily write sophisticated platform-independent networking (Internet) applications.

The URL Classes provided by Java have a great amount of functionality. In many cases, it is not necessary to explicitly use sockets in Java programming because the URL classes provide socket connections in the background for you. However, there are times when Socket Objects make the most sense to use in specific applications.

One of the questions that I am asked quite frequently is, "What is a Socket?" This is a great place to start. The technical definition of a Socket is: Sockets are the end-points of a connection between two computers. A more concrete example of Sockets can be learned from your basic 7 year old. Remember that game you played where you took two paper cups and tied them together with a length of string to form a telephone. Your friend would take one of the cups and walk to the other side of the room and talk into the cup. You would put your ear up to the other cup and be able to hear your friend. The Dixie cups in this example represent Sockets. You communicate with your friend by talking into the cup (getting an output stream from the Socket and sending bytes) and by putting your ear up to the cup to hear your friend talk (getting an input stream from the Socket and reading data from it). Sockets are used quite frequently in Java Web applications.

Have you ever wondered how the World Wide Web works? We pull up a Web Browser on the client machine and type in a URL. Now, the URL represents the address of another computer on the Internet. That other computer is known as an HTTP Web Server. The server is like a switchboard that listens for a connection request on port 80. Web servers written in Java do this by using an object known as a ServerSocket object. This object's job is to listen for a connection request on a specific port. Upon receiving a connection request, the ServerSocket creates a Socket object for the Server side in order to complete the connection. Going back to the previous example, a ServerSocket object is like a person who has a stack of paper cups, waiting to play. Whenever someone requests to play our telephone game, the ServerSocket attaches the cup to a string given to it by that person.

First, let's examine a typical interaction between a Browser and a Server. A Web Browser requests a file from the server like this:

  • First a Socket connection on port 80 is opened to the HTTP Server as mentioned above.
  • Then the browser establishes input and output streams to the Server.
  • The browser's input stream becomes the server's output stream and visa-versa.
  • Next, the browser sends a request to the server using the GET command.
GET /filename HTTP/1.0 \r\n\r\n
  • Now the browser will read the requested data from the server via its input stream.
Let's go through the basics of writing Socket-based programs in Java. The first order of business is to create a Socket Object (see Listing 1).

Notice that we needed to create the socket in a try block and catch the UnknownHostException and the IOExecption if there were any problems in creating the socket. After we create a Socket object, we need to establish input and output streams for the socket. We do this with two methods provided by the Socket class : getInputStream() and getOutputStream() (see Listing 2).

Once we have the streams, we can read from and write to them just as we would any other data source.

When we are finished using the socket, we need to close it. We close the socket as shown in Listing 3.

Those are the basics of Socket programming with Java. To recap the steps:

  1. Create a Socket object in a try block.
  2. Establish Input and Output streams in a try block.
  3. Use the streams for communication.
  4. Close the Socket in a try block when you are finished using it.

Security with Sockets and Applets
An Applet can only open a connection to the same computer that the Applet was downloaded from. This means that the only computer you will be able to open a Socket to in an Applet is the Host machine from which the Applet was downloaded. Java Applications do not have this restriction.

Writing a Client-Side Application
With this background information, let us write a Client-Side Java application using Sockets that connects to a Web server. Upon completing a Socket connection, we will request a Web page and then display the HTML code in a text area. Please refer to the source code for SocketClient.java for a step-by-step analysis.

First we have to import the awt, io and net class library packages. The class, SocketClient, extends Frame and implements the Runnable interface. We need a Frame Window object to contain the program because we wish to use the AWT in an application. The Runnable interface is implemented so that we can use this object with a thread.

The constructor sets up the various window GUI components. We then create a new Thread and feed it the application as the Runnable object. We will get into the thread's purpose later. Next, we resize the window and show it to our viewing audience. That's all for the constructor of this class.

The next method is the handleEvent(Event e) method. This method will handle three events:

  • The user presses the "Get the file" button.
  • The user presses the "Stop" button.
  • The user exits the program.
If the "Get the file" button was pressed, we first want to stop whatever else we were doing so that we can get the file. Next, we need to see if the user actually entered a file name. If not, we will use index.html as a default file name. We then display a message in the window so that the user knows that we are connecting to the server that they have specified. Next, we create a new thread and start it. We then return true. When we started the thread, the run() method is invoked for the thread's Runnable object. We will use this run() method to do the work for us.

If the "Stop" button is pressed, we just stop the thread and return true after displaying a message for the user. The last event we handle here is if the user exits the program. We look for a WINDOW_DESTROY event as our signal to exit the program.

Notice how we are returning super.handleEvent(e). If we do not handle the event, it is a good idea to pass it along up the chain to our parents. The super keyword calls the parent class to handle the event. That concludes our event handling portion of this program.

Now let's analyze the run() method. This is where the real work gets done. Before we get into it, notice a single try block embedded within the run() method! If we look at the end, we notice a single catch block for all of the exceptions. I mentioned earlier that we need to catch several different types of exceptions for these various statements in this method. However, since most of the code in this method has to be tried and caught, we do not lose any noticeable efficiency in trying the whole method like this. Also, since UnknownHostException and IOException are derived from Exception, we only really need to catch an Exception Object. The rule here is UnknownHostException IS-A Exception. This is a handy technique to remember.

First, we create the Socket object to the specified server on port 80. After the connection is complete, we establish the streams. I have combined a few steps into two lines of code. Since I personally like DataInputStream and DataOutputStream, I created those by feeding their constructors the streams returned by Socket's getInputStream() and getOutputStream() methods.

At this point, we can request a file. We create a request string and write it to the DataOutputStream after displaying it in the window for the user. Remember to flush() the output stream to make sure the whole message is sent to the server. With the request sent, we can now read the DataInputStream for the requested file. We read this stream just like any other data source. We read a line at a time until we reach the end of the file and store it in a string buffer. When we are finished reading the data, we display it in the window for the user to see. To finish off, we close the socket connection.

The thread was needed here so that the run method could execute in sort of a multi-tasking fashion. We want to be able to interrupt with the stop button just like we would in a browser. Since we need a way to interrupt the process of downloading a HTML file or a stuck connection, a thread makes things run smoothly.

Since this is an application, we need the public static void main(String[] args) method. Here, we just create this object to get things rolling.

Conclusion
That's it! You now know how to write a Socket Based Client Program using Java. As an interesting experiment, try to write a similar program using the URL class to do the same thing. Here is where the people who created these java.net libraries are greatly appreciated.

import java.awt.*;
import java.io.*;
import java.net.*;

This SocketClient application was written for educational purposes. It teaches you how to write a Socket Based Client Program in JavaŠ. This program opens a socket to a Web server on the Internet running on Port 80. It requests a HTML page and displays its source HTML code in a Text Area.

This same method of Socket manipulation can be used to write any Client Socket-Based Application. Just change the port number to that of your server program.

About the Author
Joseph M. DiBella is the Senior Java Instructor and Curiculum Developer for Computer Educational Services in New York City. He also is the President of HMJ Electronics, a computer consulting company which develops software and Java-enhanced Web sites.

	

Listing 1: Create a Socket Object

	try{
		ourSocket = new Socket(serverName, 80);
	}catch(UnknownHostException e){
		//..code if the host does not exist
	}catch(IOException e){
System.out.println(" Unable to open the Socket to "+serverName);
	}

Listing 2: Establish input and output streams.

	try{
		ourInputStream = ourSocket.getInputStream();
		ourOutputStream = ourSocket.getOutputStream();
	}catch(IOException e){
		System.out.println("unable to open streams");
	}

Listing 3: Closing the socket.

	try{
		ourSocket.close();
	}catch(IOException e){
		System.out.println("Exception thrown closing the Socket");
	}

Listing 4

 */
public class SocketClient extends Frame implements Runnable{
    /* *******   Data Section    ******** */
    TextField theServer,theFile;
    TextArea theHTMLCode;
    Thread thread;
    Button search, stopSearch;
    Socket ourSocket;

/**
* This is the default constructor for this class. Its job is to initialize
* the SocketClient object. We construct a Frame Window here. A data entry
* panel is created and added "North". Here a user will be able to enter a server
* name and a file to retrieve. If no file name is specified, index.html will be the
* default file to search for.*/
    public SocketClient(){

        setTitle("Socket Client Example");   
//Set the frame window title.
        setLayout(new BorderLayout());       
//Set the layout for the window.
        theServer = new TextField("www.",20);
//Create the data entry fields.
        theFile = new TextField("",20);
        theHTMLCode = new TextArea("",25,100);
        theHTMLCode.setEditable(false);      
//Make the TextArea not editable.

        Panel pan = new Panel();             
//Make a panel to contain the data
        pan.setLayout(new FlowLayout());     
//  entry fields and set the layout.
        pan.add(new Label("http://"));       
//Add text labels to the panel as
        pan.add(theServer);                  
//  well as the Data Entry Objects.
        pan.add(new Label("/"));
        pan.add(theFile);
        search= new Button("Get the file");
        stopSearch= new Button("Stop");

        pan.add(search);
        pan.add(stopSearch);


        add("North",pan);                   
//Add the panel North.
        add("Center",theHTMLCode);          
//Add the TextArea Center.

        thread = new Thread(this);          
//Create a new thread.
        resize(640,300);                    
//Resize the Window to an appropriate size.
        show();                             
//Display the Window.
    }

Listing 5: HandleEvent Method.

/**
* This is the handleEvent method. We provide code for the events triggered
* from a user pressing a button or destroying the window (Exiting the program).
* @param Event e
* @see event*/
    public boolean handleEvent(Event e){
    if(e.target == search){         
//If the Search Button was pressed, do this.
    thread.stop();
    if(theFile.getText().equals("")){   
//If no file was specified
    theFile.setText("index.html");  
//  set the file name to index.html.
            }
    theHTMLCode.setText("Looking Up Server: "+theServer.getText());
    thread = new Thread(this);
    thread.start();                     
//This calls the run() method for this.
            return true;
        }
        if(e.target == stopSearch){     
//If the Stop Button was pressed, do this.
    thread.stop();
    theHTMLCode.setText("Operation aborted by user");
    return true;
        }
        if(e.id ==Event.WINDOW_DESTROY){    
//If the user wants to exit the program.
            System.exit(0);                 
//Notice how we do not need to return here.
        }
        return super.handleEvent(e);        
//If we do not handle the event, pass it up the chain.
    }

Listing 6: Run Method

/**
* This is the run method. It will open a socket connection to a web server and then
* get the input and output streams.  Then we will simulate the way a web browser
* asks the server for a file with the GET statement. After that, we  will read the
* text data from the web server.*/
    public void run(){
        //Get the Socket and Streams
        try{
     ourSocket = new Socket(theServer.getText(),80);
     DataInputStream inStream   
//Notice how we kill a few birds with one stone.
   = new DataInputStream(ourSocket.getInputStream());
     DataOutputStream outStream 
//Here too!
   = new DataOutputStream(ourSocket.getOutputStream());
         

Listing 7: File Request String.

/* Here we construct a file request string.  Since we are using
* a HTTP server, we need to simulate a file request. We do this
* like: GET /filename HTTP/1.0\r\n\r\n
* Notice that two  ctrl/lf sequences are needed at the end of the request*/
  String requestString ="GET /"+ theFile.getText()+" HTTP/1.0\r\n"+ "\r\n";
  theHTMLCode.appendText("\n The Request String is:\n"+requestString);
  outStream.writeBytes(requestString); 
//Send the Request to the HTTP server
            outStream.flush();                   
//Don't forget to flush the stream.
            theHTMLCode.appendText
			("\n ....Asking for file:"+theFile.getText());

        //Read the file until EOF.
            StringBuffer buff = new StringBuffer();
            String currLine;
            while((currLine = inStream.readLine())!=null){
                buff.append(currLine + "\n");
            }
            theHTMLCode.setText(buff.toString()); 
//Place the text into the Text Area.

        //Close the Socket
            ourSocket.close();

        }
        catch(Exception e){  
/* Since several exceptions can be thrown, We can catch all of them
* with the base class for Exceptions.*/
     theHTMLCode.setText("Exception with: "+e.getMessage()+"\n"+e.toString());
        }
    }

Listing 8: Main Method.

    /** This is the main method. Program execution begins here
    */
    public static void main(String[] args){
        new SocketClient();
    }

}


 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.