Writing servers

Introduction

So far we have only looked at clients in Java, assuming that servers were ready and available. It is just as easy to write a server in Java. The new library class involved is the ServerSocket class. Servers often use multi-threading.

A Socket object is a connection to a particular host on a particular port. But a SocketServer object just waits on a particular port for incoming connections from anywhere. When a client attempts to connect, the server wakes up and a Socket object is created. Thereafter the server uses the socket to send and receive data. So:


The ServerSocket class

This class, together with the Socket class, provide all the facilities necessary to write servers in Java. It provides methods to:

The general algorithm for a server is:

  1. A ServerSocket object is created on a particular port
  2. The ServerSocket object listens for any connection attempts using the method accept. The server is blocked (waits) until a client attempts to connect. When a client connects, method accept returns a Socket object representing the connection between the server and the client.
  3. The Socket object's getInputStream and/or getOutputStream methods are called to obtain streams which can be used to send and receive data. (This is the same mechanism as we saw with a client.)
  4. The server and the client interact using streams according to an agreed protocol.
  5. The server, the client, or both close the connection.
  6. The server returns to step 2, to wait for the next connection.

 

Although this is a general pattern, a different approach is needed if the communication between client and server (step 4) is time-consuming.


Example - A daytime server

This is one of the simplest servers, implementing the daytime protocol. The client connects, but sends no data. The server simply sends the time and date as a text string and then closes the connection.

The server waits for connections by calling accept, within an infinite loop. When a client connects, a new Socket object is created. The date is obtained by calling the library class Date. After dispatch of the information, the socket (but not the ServerSocket) is closed.

 

Pseudocode

create a server socket on port 13
while true do
    wait for a connection from a client
    look up the date and time
    send the date and time to the client
    close socket
endWhile

 

Java

import java.net.*;
import java.io.*;
import java.util.Date;
 
public class DaytimeServer {
 
   public final static int daytimePort = 13;
 
    public static void main(String[] args) {
        ServerSocket server;
        Socket socket;
 
        try {
            server = new ServerSocket(daytimePort);
            try {
                while (true) {
                    socket = server.accept();
                    PrintWriter out = new
                         PrintWriter(socket.getOutputStream(), true);
                    Date date = new Date();
                    out.println(date.toString());
                    socket.close();
                 }
            }
            catch (IOException e) {
                server.close();
                System.err.println(e);
            }
        }
        catch (IOException e) { System.err.println(e);}
    }
}

 


A web server

Finally we look at the design and code of a web server - a server that implements HTTP. This is a large protocol and a full-blown server would need to:

import java.net.*;
import java.io.*;
import java.util.*;
 
public class WebServer {
 
   public final static int webPort = 80;
   public final String docRoot = "C:\\webpages\\";
   BufferedReader in;
   PrintWriter out;
 
    public static void main(String[] args) {
        WebServer ws = new WebServer();
        ws.waitForRequest();
    }
    
    public void waitForRequest() {
        
        ServerSocket server;
        Socket socket;
 
        try {
            server = new ServerSocket(webPort);
            try {
                while (true) {
                    socket = server.accept();
                    serviceRequest(socket);
                    socket.close();
                 }
            }
            catch (IOException e) {
                server.close();
                System.err.println(e);
            }
        }
        catch (IOException e) { System.err.println(e);}
    }
    
    public void serviceRequest(Socket socket) {
        try {
            in = new BufferedReader(
                new InputStreamReader(
                    socket.getInputStream()));
 
            out = new PrintWriter(socket.getOutputStream(), true);
            String line = in.readLine();
            StringTokenizer st = new StringTokenizer(line);
            String command = st.nextToken();
            if (command.equals("GET")) {
                sendFile(st.nextToken());
                skipRemainder();
            }
            else
                notImplemented();
            socket.close();
        }
        catch (IOException e) {}
    }
 
    public void sendFile(String fileName) {
        try {
            String completeName = docRoot + fileName;
            BufferedReader file = new BufferedReader(
                           new FileReader(completeName));
            sendHeader((new File(completeName)).length());
            String line;
            while ((line = file.readLine()) != null)
                out.println(line);
        }
        catch (IOException e) {fileNotFound();}
    }
 
    public void skipRemainder() {
    }
 
    public void sendHeader(long length){
    }
 
    public void fileNotFound() {
    }
 
    public void notImplemented() {
        out.println("<HTML><HEAD>Not Implemented</TITLE></HEAD>");
        out.println("<BODY><H1>HTTP Error 501:" +
                              "Not Implemented</H1></BODY></HTML>");
    }
 
}

Multi-threading

A server may be bombarded with requests from a number of different clients within a short time. If the server program accepts the first request but then dedicates itself exclusively to servicing it, all other requests will be locked out. The above server program blocks (waits) on the readLine statement while a line is transferred from slow disk storage. While it is waiting, nothing else can be done. Therefore it is common practise to create a new thread to handle each client. These run concurrently and any one can be blocked while others continue. Java provides facilities for this multi-threading.


Summary

The Java library class ServerSocket allows a server program to wait for a connection from a client.


Summary of class ServerSocket

class name

ServerSocket

import

import java.net

 

method

description

example

constructors

 

 

public ServerSocket(int port)

creates a server socket on the port specified

ServerSocket ss = new ServerSocket(13);

 

 

 

object methods

 

 

public Socket accept()

Waits until a client connects. Returns a socket object representing the connection.

Socket s = ss.accept();

public void close()

closes the server socket. Frees up the port.

Note: not the same as closing a socket.

ss.close();

public String toString()

returns a string which is the number of the local port

String port = ss.toString();

 


Quiz

What are the differences between a socket and a server socket?

Demos

1 If you are using Windows, open the DOS window and type the following to see which of your ports are open:

netstat -a

2 Go to the following site and ask it to probe your ports:

www.grc.com

3 Go to this site to see how vulnerable your computer may be:

privacy.net/analyze

Exercises

1 Run the daytime server given above in the text and test it with either telnet or the daytime client (code given earlier).

You can run the server on one PC, with the client either on the same machine or a different PC. When you run the client program, you can type in localhost as the host name to get the time from.

2 Augment the daytime server by adding a logging facility, so that it displays in a text area the names of clients who have connected.

3 Run and test the web server program given in the text, using a telnet program as a client.

4 Complete the empty methods within the web server (HTTP server) program given in the text. These are skipRemainder sendHeader and fileNotFound

5 (Big project) Enhance the web server program with the following facilities: