Programming Servers Using Sockets
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 to and from that client. So:
The ServerSocket class
This class, together with the Socket class, provides all the facilities necessary to write servers in Java. It provides methods to:
In general the server works like this:
Although this is a general pattern, things are not always so simple, and 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 in 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. Here is the relevant
Program 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 the socket endWhile
// DaytimeServer.java // Provides the date and time on the current server // at port number 7013. import java.net.*; import java.io.*; import java.util.Date; public class DaytimeServer { public final static int DAYTIME_PORT = 7013; public static void main(String[] args) { ServerSocket server; Socket socket; try { server = new ServerSocket(DAYTIME_PORT); 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 Simple 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:
// WebServer.java // Serves up static HTML web pages from a // local subdirectory called "webpages". import java.net.*; import java.io.*; import java.util.*; public class WebServer { public final static int WEB_PORT = 7080; public final String docRoot = "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(WEB_PORT); 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><TITLE>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. This is a common practice, 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.
So, the Java library class ServerSocket allows a server program to wait for a connection from a client, and then deal with that client.
Class name: |
ServerSocket |
Import: |
|
Summary of class ServerSocket
Method |
Description |
Example |
Constructors: |
|
|
public ServerSocket(int port) |
Creates a ServerSocket 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 ServerSocket. Frees up the port. Note that this is 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(); |
Question: What are the differences between a socket and a server socket?
Informative Demos
netstat -a
www.grc.com
privacy.net/analyze
Exercises