Documente Academic
Documente Profesional
Documente Cultură
John Morris
Overview
To create a simple HTTP server in Java To use the implementation to illustrate a number of advanced Java features:
TCP/IP Sockets and Server Sockets Interfaces Software components (more from John later) Multithreading
To show how to create executable server objects (using Suns Servlets API)
Recommended Reading
Java Network Programming, Elliotte Rusty Harold, OReilly and Associates, 1997, ISBN 1-56592-227-1 TCP/IP Network Administration, Second Edition, Craig Hunt, OReilly and Associates, 1997, ISBN 1-56592-322-7 The Java Developers connection: http://www.javasoft.com/jdc The Javadoc documentation
(Pseudo) requirements
Server must be able to process HTTP/1.0 file transfer requests and deliver files Connections are to be made via TCP/IP Must be efficient and prompt Must be simple to understand and elegant in design
HTTP protocol
Developed by Tim Berners-Lee at CERN Like most Internet protocols it is described in an RFC (Request for Comment document): RFC1945 May be downloaded from the Internet Engineering Task Forces web site: http://www.ietf.org
HttpServer
ServerSocket socket = new ServerSocket(80, 5); public void listen() throws IllegalAccessException, InstantiationException, IOException { for (;;) { System.err.println("HttpServer: waiting..."); Socket s = socket.accept(); FileServer f = createFileServer(); f.dispatch(s); } }
Client (sid)
s = new Socket (fred, 80)
Server (fred)
2037 80
ServerSocket ss. s = ss.accept()
2037
1583
Socket s
1583 s.getInputStream()
s.getOuputStream()
public void listen() throws IllegalAccessException, InstantiationException, IOException { for (;;) { System.err.println("HttpServer: waiting..."); Socket s = socket.accept();
FileServer f = createFileServer(); f.dispatch(s); } }
Client Program
Interface
Software Component
/ublic class HttpServer { /** Listens indefinitely for transfer requests and creates a server instance for each request. */ public void listen() throws IllegalAccessException, InstantiationException, IOException { for (;;) { /* Block, waiting for a request to occur then spawns a new (anonymous) socket with which to deal with the request. */ System.err.println("HttpServer: waiting..."); Socket s = socket.accept(); /* Create a file server to deal with the new socket. */ FileServer f = createFileServer(); f.dispatch(s); } } public static void main(String[] args) { try { HttpServer htts = new HttpServer("sea.server.ThreadedFileServer"); htts.listen(); } catch (Exception e) { System.err.println("HttpServer: failed due to exception:\n" + e); } }
Implementing FileServer
Two flavours of FileServer have been provided using deferred instantiation
A simple one but with low performance: sea.server.SimpleFileServer A server that uses multiple threads to increase performance: sea.server.ThreadedFileServer A server which uses a pool of threads to achieve the maximum possible performance: sea.server.ThreadedServer2
SimpleFileServer (1)
Must implement the FileServer interface so that it can plug in to the HttpServer Reads the HTTP request from the Sockets input stream Decides which file is required Reads the file and spools to the Sockets output stream.
SimpleFileServer (2)
public class SimpleFileServer implements FileServer { protected Socket s = null; public void dispatch(Socket s) { this.s = s; respond(); } . . . .
SimpleFileServer (3)
Must get an input stream so that we can analyse the request Socket provides the method
InputStream getInputStream();
Socket s;
InputStream inStream = s.getInputStream(); InputStreamReader reader = new InputStreamReader(inStream); BufferedReader input = new BufferedReader(reader);
SimpleFileServer (4)
Request consists of a number of lines of text separated by \r\n First line is all this server is interested in A typical request might be of the form:
GET /path/to/file.html HTTP/1.0 Accept: text/html Accept: image/gif User-Agent: Lynx/2.4
SimpleFileServer (5)
Cuts out the file name Looks for the file relative to the current working directory (not portable!!) If the file is a directory look for the file index.html in the directory If the file does not exist then respond with an error (code 404)
SimpleFileServer (6)
Must construct a header for the response Code 200 means success Simple header takes the following form:
HTTP/1.0 200 OK Server: SEA/1.0 MIME-version: 1.0 Content-type: text/html
SimpleFileServer (7)
Get the output stream from the Socket
OutputStream getOutputStream()
Spool (copy) the file contents into the socket If the MIME type is textual then we must make sure the lines are delimited by \r\n. Otherwise we pass the file unmodified
Reading a file from disk takes a long time (around 10ms) The server will be sitting idle while it waits for the file to load (wasting up to 106 instruction cycles) Other web browsers will be kept waiting
time
Start HTTP request loading Block awaiting disk availability Deliver web page across network
time
java.lang.Thread (1)
Creates new threads within the virtual machine Classes which start threads must implement interface java.lang.Runnable
interface Runnable { /** This is the method that will be run when the new thread is started. */ public void run(); }
java.lang.Thread (2)
Must create a Thread object associated with each new thread using the constructor
Thread(Runnable run, String threadName)
Other useful methods can be used to set priorities and interrupt a running thread
java.lang.Thread (3)
Our threads do not share any common memory locations (except for index) When threads read/write a shared memory area access must be synchronized Otherwise it is impossible to predict how the system will behave Java has mechanisms for achieving this
We need to be able to run programs within the server to process user requests
Accept a client request including arguments Run a program on the arguments Return results in the form of a document
Servlets
When we run small Java programs within a browser these are referred to as Applets. . . so we run small Java programs within a server these are Servlets A servlet is a program designed to process a client request (which requires interactivity).
It processes arguments and formats its results as a short lived document.
HTML servlets are becoming a popular mechanism for creating interactive servers.
This may optionally be overridden to initialise the state of the servlet (for example loading state information from a file).
If you wish to save to servlet state to a file (or using JDBC) this is the method to override
If a browser visits your servlet this is where you get to create a document for it to display
If your document contains an HTML form and the user posts the results this is where you can extract and process them
Also methods for HTTP OPTIONS, TRACE and DELETE (more exotic options)
ChatServer (1)
public class ChatServlet extends HttpServlet { Vector messages = new Vector(); public void init(ServletConfig config) throws ServletException { super.init(config); } public void destroy() { // Currently does nothing } . . . . }
ChatServer (2)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { createDocument(response); } protected void createDocument(HttpServletResponse response) throws IOException { response.setContentType("text/html"); response.setHeader("pragma", "no-cache"); PrintWriter writer = response.getWriter(); writer.println("<HTML>"); writer.println("<HEAD><TITLE>Chat Servlet</TITLE></HEAD>"); writer.println("<BODY>"); Date now = new Date(); writer.println("Current server time is " + now + "<P>"); . . . . writer.println("</BODY></HTML>"); writer.close(); }
ChatServer (3)
for (int i = 0; i < messages.size(); i++) { writer.println("<HR>"); String messageString = (String) messages.elementAt(i); writer.println(messageString); }
writer.println("<HR><FORM METHOD=POST>"); writer.println("Enter your name: + <INPUT TYPE=TEXT SIZE=25 NAME=name><BR>"); writer.println("Enter your message:<BR> + <TEXTAREA ROWS=5 COLS=40 NAME=message> + Type your message here</TEXTAREA><BR>"); writer.println( "<INPUT TYPE=SUBMIT NAME=action VALUE=Submit>"); writer.println("<HR></FORM>");
ChatServer (4)
protected synchronized void doPost( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); String message = request.getParameter("message"); if (name != null && message != null) { Date timeStamp = new Date(); String messageString = "<B>Message " + messages.size() + " from " + name + " at " + timeStamp + ":</B><BR>" + message + "<P>"; messages.add(messageString); } createDocument(response); }
Performance (1)
Servlets offer better performance than most of the previous CGI like technologies But CGI/Servlets concentrate the load on the server When designing high throughput servers only use servlets where you really need interactivity
Searches/Shopping carts Data that is very short lived (stock quotes)
This also applies to low throughput servers that might need to scale later
Performance (2)
Consider using periodic programs to generate static documents on disk
The cost of serving fixed documents will always be less than the cost of server side execution Disk space is cheap!
HTTP (& TCP/IP services in general) transfer documents on the users request To push updates automatically from the server you will need to:
Start a reverse server within each client Use a multicast group Use a remote procedure call system such as RMI or CORBA
Homework
Read through the sample code to convince yourself you understand whats going on Sample code can be downloaded from http://ciips.ee.uwa.edu.au/~gareth Read the code documentation If you can, run the examples to check they work
Comments, Suggestions. . .
How was the presentation paced? Was there enough (or too much) technical content? Any areas of particular interest? Comments regarding presentation style?