Chapter 26
Java Socket Programming
by Stephen Ingram
--------------------------------------------------------------------------------
CONTENTS
An Introduction to Sockets
Java Connection-Oriented Classes
Java Datagram Classes
An HTTP Server Application
Summary
--------------------------------------------------------------------------------
For full Java client/server applet connectivity, an applet server is required. This chapter initiates the development of a Java HTTP server. Before beginning the development of the server, however, you need some background knowledge of socket programming. This chapter begins with a socket overview followed by an exploration of Java's socket classes. The remainder of the chapter focuses on the construction of a Java HTTP Web server.
After reading this chapter, you should be able to do the following:
Understand the socket abstraction
Know the different modes of socket operation
Have a working knowledge of the HTTP protocol
Be capable of applying the Java socket classes
Understand applet socket use and limitations
Comprehend the HTTP Java server
An Introduction to Sockets
The computers on the Internet are connected by the TCP/IP protocol. In the 1980s, the Advanced Research Projects Agency (ARPA) of the U.S. government funded the University of California at Berkeley to provide a UNIX implementation of the TCP/IP protocol suite. What was developed was termed the socket interface (although you may hear it called the Berkeley-socket interface or just Berkeley sockets). Today, the socket interface is the most widely used method for accessing a TCP/IP network.
A socket is nothing more than a convenient abstraction. It represents a connection point into a TCP/IP network, much like the electrical sockets in your home provide a connection point for your appliances. When two computers want to converse, each uses a socket. One computer is termed the server-it opens a socket and listens for connections. The other computer is termed the client-it calls the server socket to start the connection. To establish a connection, all that's needed is a server's destination address and port number.
Each computer in a TCP/IP network has a unique address. Ports represent individual connections within that address. This is analogous to corporate mail-each person within a company shares the same address, but a letter is routed within the company by the person's name. Each port within a computer shares the same address, but data is routed within each computer by the port number. When a socket is created, it must be associated with a specific port-this process is known as binding to a port.
Socket Transmission Modes
Sockets have two major modes of operation: connection-oriented and connectionless modes. Connection-oriented sockets operate like a telephone: they must establish a connection and then hang up. Everything that flows between these two events arrives in the same order it was sent. Connectionless sockets operate like the mail: delivery is not guaranteed, and multiple pieces of mail may arrive in a different order than they were sent.
The mode you use is determined by an application's needs. If reliability is important, connection-oriented operation is better. File servers must have all their data arrive correctly and in sequence. If some data is lost, the server's usefulness is invalidated. Some applications-time servers, for example-send discrete chunks of data at regular intervals. If data were to get lost, the server would not want the network to retry because by the time the resent data arrived, it would be too old to have any accuracy. When you need reliability, be aware that it does come with a price. Ensuring data sequence and correctness requires extra processing and memory usage; this extra overhead can slow down the response times of a server.
Connectionless operation uses the User Datagram Protocol (UDP). A datagram is a self-contained unit that has all the information needed to attempt its delivery. Think of it as an envelope-it has a destination and return address on the outside and contains the data to be sent on the inside. A socket in this mode does not have to connect to a destination socket; it simply sends the datagram. The UDP protocol promises only to make a best-effort delivery attempt. Connectionless operation is fast and efficient, but not guaranteed.
Connection-oriented operation uses the Transport Control Protocol (TCP). A socket in this mode must connect to the destination before sending data. Once connected, the sockets are accessed using a streams interface: open-read-write-close. Everything sent by one socket is received by the other end of the connection in exactly the same order it was sent. Connection-oriented operation is less efficient than connectionless operation, but it's guaranteed.
Sun Microsystems has always been a proponent of internetworking, so it isn't surprising to find rich support for sockets in the Java class hierarchy. In fact, the Java classes have significantly reduced the skill needed to create a sockets program. Each transmission mode is implemented in a separate set of Java classes. This chapter discusses the connection-oriented classes first.
Java Connection-Oriented Classes
The connection-oriented classes within Java have both a client and a server representative. The client half tends to be the simplest to set up, so we cover it first.
Listing 26.1 shows a simple client application. It requests an HTML document from a server and displays the response to the console.
--------------------------------------------------------------------------------
Listing 26.1. A simple socket client.
import java.io.*;
import java.net.*;
/**
* An application that opens a connection to a Web server and reads
* a single Web page from the connection.
*/
public class SimpleWebClient {
public static void main(String args[])
{
try
{
// Open a client socket connection
Socket clientSocket1 = new Socket("www.javasoft.com", 80);
System.out.println("Client1: " + clientSocket1);
// Get a Web page
getPage(clientSocket1);
}
catch (UnknownHostException uhe)
{
System.out.println("UnknownHostException: " + uhe);
}
catch (IOException ioe)
{
System.err.println("IOException: " + ioe);
}
}
/**
* Request a Web page using the passed client socket.
* Display the reply and close the client socket.
*/
public static void getPage(Socket clientSocket)
{
try
{
// Acquire the input and output streams
DataOutputStream outbound = new DataOutputStream(
clientSocket.getOutputStream() );
DataInputStream inbound = new DataInputStream(
clientSocket.getInputStream() );
// Write the HTTP request to the server
outbound.writeBytes("GET / HTTP/1.0\r\n\r\n");
// Read the response
String responseLine;
while ((responseLine = inbound.readLine()) != null)
{
// Display each line to the console
System.out.println(responseLine);
// This code checks for EOF. There is a bug in the
// socket close code under Win 95. readLine() will
// not return null when the client socket is closed
// by the server.
if ( responseLine.indexOf("