Saturday, December 27, 2014

Custom Java based webserver for static resource

My title


Web Server is as per name concern – The origin of Server is to serve, technically means that the specific computer serving for all others computer that are belongs in the network. Or we can say an application program that accepts connections in order to service requests by sending back responses. Any given program may be capable of being both a client and a server; our use of these terms refers only to the role being performed by the program for a particular connection, rather than to the program’s capabilities in general. Likewise, any server may act as an origin server, proxy, gateway, or tunnel, switching behavior based on the nature of each request. So, when the server serves through HTTP protocol then it’s called Web Server. That’s why a Web Server also called a Hypertext Transfer Protocol (HTTP) server because it uses HTTP to communicate with its clients, which are usually web browsers.
A Java Based Web Server basically stands on two classes of java.net packages. One java.net.Socket and another java.net.ServerSocket and communicates are done through HTTP messages. So it is essential to give a summery on those three things before going to the application part.
HTTP (Hypertext Transfer Protocol)1.1:
          HTTP is a generic, stateless protocol in application layer of TCP/IP network model or Presentation layer of the OSI network model for distributed, collaborative and hypermedia information system. These models are abstract.
          The first version HTTP-0.9 was a simple protocol for raw data transfer over internet. HTTP-1.0, is allowing message to be in the format of MIME (Multipurpose Internet Mail Extensions i.e. email support, text in character rather then ASCII) like messages. HTTP-1.1, is allowing simple retrieval, including search front end update etc.
          The HTTP protocols are responsible for sending and receiving data from browser to web server or vice versa. Or we can say it is a simple Request Response Protocol. The connection between browsers to server is based on the Server IP address and the "port" or channel that the server is listening on.
Request:
Client sent a request to the server in the form of Request method, URI (Uniform Resource Identifier) and Http version. Followed by a MIME-like message containing request modifiers, client information, and possible body content over a connection with a server.
                   POST /examples/default.jsp HTTP/1.1

Response:
The server responds with a status line, including the message’s protocol version and a success or error code, followed by a MIME-like message containing server information, entity meta information, and possible entity-body content.
                   HTTP/1.1 200 OK
Java.net.Socket:
          This class is responsible for read and writes information from the network or we can say it is the end point of the application. Via Http protocol information or data are transferred from client machine to server. Next responsibility starts of the Socket for reading and writing information to Http protocol. Each and every socket has an address i.e. the combination of an IP address (the location of the computer) and a port (which is mapped to the application program process) into a single identity, much like one end of a telephone connection is the combination of a phone number and a particular extension.
          We can directly create the instance of Socket class using new key word with passing parameters or calling the accept() method of ServerSocket class which return the instance of Socket class. Here in the application we will basically use the second approach.
new Socket (“localhost”, 555);                // A simple Socket Instance port no
should be as the mentioned port no in the Server Socket class.
            new ServerSocket(555,1,InetAddress.getByName("127.0.0.1")).accept();
// First parameter is port no second parameter the maximum queue length of incoming connection requests before the server socket starts to refuse the incoming requests
Once we create an instance of the Socket class successfully, we can use it to send and receive streams of bytes. To send byte streams, we need to call getOutputStream method to obtain a java.io.OutputStream object. To receive byte streams from the other end of the connection, we need to call the getInputStream method, which returns a java.io.InputStream.
Java.net.ServerSocket:
          The role of a server socket is to wait for connection requests from clients. Once the server socket gets a connection request, it creates a Socket instance to handle the communication with the client.
          The ServerSocket may be HttpServer or FTP server. This server must stand by all the time as it does not know when a client application will try to connect to it or whenever the request will come from client. There are four constructor of the ServerSocket class but we are basically using the following constructor –
new ServerSocket(555,1,InetAddress.getByName("127.0.0.1"));
// First parameter is port no second parameter the maximum queue length of incoming connection requests before the server socket starts to refuse the incoming requests
Application:
          This is a simple application which contain three classes
·         HttpServer
·         Request
·         Response
This application only serves for the static resource such as .html, .jpg, .xml etc. Dynamic resource such as Servlet’s are not integrated with it.
Application Directory : D:\test-application\jserver
jserver is the application name and all of the classes are belongs in the test.server package.
HttpServer: The HttpServer class represents a web server
package test.server;
/**
 *
 * @author prashanta.majhi
 */
import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.io.*;
/**
 * * @author prashanta.majhi
 */
public class HttpServer {
    public static final String WEB_ROOT = "D:/test-application/jserver";
   // This indicate the root directory of the server such
                        //as webapps of Apache tomcat server.
    private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
   // This is use for shutdown the server from browser.
    private boolean shutdown = false;
    public static void main(String [] args){
        new HttpServer().await();
    }
    public void await(){
        ServerSocket serversocket=null;
        int port=1111;
        Socket socket=null;
        InputStream input=null;
        OutputStream output=null;
        try{
            serversocket=new ServerSocket(port,1,InetAddress.getByName("127.0.0.1"));
        }catch(Exception e){
            e.printStackTrace();
            System.exit(1);
        }
        while(!shutdown){
            try{
                socket=serversocket.accept();
                //return the instance of Socket class
                input=socket.getInputStream();
                // return input stream.
                output=socket.getOutputStream();
                //return output stream
                 Request request=new Request(input);
                 // create the instance of the Request
                    //using input stream of socket.
                request.parse();
                Response response=new Response(output);
                // create the response object
                //using output stream of socket.
                response.setRequest(request);
                response.sendStaticResource();
                // This part we are now returning the static
                //response only. For servlet we need to
                //integrate the servlet.jar file with it and need to passing
                //these two object into its service method. But here we
                //have only concentrating on static response.
                socket.close();
                shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
            }catch(Exception e){
                e.printStackTrace();
                continue;
            }
        }
    }
}
Request: Request class represents an HTTP request. An instance of this class is constructed by passing the InputStream object obtained from a Socket that handles the communication with the client.
package test.server;
import java.io.IOException;
import java.io.InputStream;
public class Request {
    private InputStream input=null;
    private String uri;
    public Request(InputStream input){
        this.input=input;
    }
    public void parse(){
        StringBuffer request = new StringBuffer(2048);
        int i;
        byte[] buffer = new byte[2048];
        try {
            i = input.read(buffer);
        } catch (IOException e)
        { e.printStackTrace();
          i = -1;
        }
        for (int j=0; j<i; j++) {
            request.append((char) buffer[j]);
        }
        System.out.print(request.toString());
        uri = parseUri(request.toString());
    }
    public String parseUri(String requestString){
        System.out.println("before parsing URI="+requestString);
         int index1, index2;
         index1 = requestString.indexOf(' ');
         if (index1 != -1)
         {
             index2 = requestString.indexOf(' ', index1 + 1);
             System.out.println("URI="+requestString.substring(index1 + 1, index2));
             if (index2 > index1)
               return requestString.substring(index1 + 1, index2);
         }
         return null;
    }
    public String getUri(){
        return uri;
    }
}
The parse method parses the raw data in the HTTP request. The parseUri method stores the URI in the uri variable. The public getUri method is invoked to return the URI of the HTTP request.
Response:
A Response object is constructed by the HttpServer class’s await() method by passing the OutputStream object obtained from the socket.
package test.server;
/**
 *
 * @author prashanta.majhi
 */
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
public class Response {
    private static final int BUFFER_SIZE = 1024;
    Request request;
    OutputStream output;
    public Response(OutputStream output){
        this.output=output;
    }
    public void setRequest(Request request){
        this.request=request;
    }
    public void sendStaticResource() throws Exception{
        byte[] bytes=new byte[BUFFER_SIZE];
        FileInputStream fis=null;
        try{
           File file=new File(HttpServer.WEB_ROOT,request.getUri());
  // Create the instantiates of java.io.File class by p
           //passing the parent path and child path to the File
           // class's constructor. Then check where file is exists or
           // not if yes then constructs a java.io.FileInputStream object
           //by passing the File object. Then, it invokes the read method of
           //the FileInputStream and writes the byte array to the OutputStream
           //output.
           if(file.exists()){
              fis=new FileInputStream(file);
              int ch = fis.read(bytes, 0, BUFFER_SIZE);
              while(ch!=-1){
                  output.write(bytes, 0, ch);
                  ch = fis.read(bytes, 0, BUFFER_SIZE);
              }
           }
        else{
            String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +
                    "Content-Type: text/html\r\n" +
                    "Content-Length: 23\r\n" +
                    "\r\n" +
                    "<h1>File Not Found</h1>";
output.write(errorMessage.getBytes());
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
The Response class has two public methods: setRequest and sendStaticResource method. The setRequest method is used to pass a Request object to the Response object. The sendStaticResource method is used to send a static resource, such as an HTML file.
After completing all of those things compile those classes. Place a html file into its root directory which have been mention in HttpServer class as WEB_ROOT. Run the HttpServer class.
To test the application open the browser and type the following in the URL
filename.html belong at D:/test-application/jserver.

No comments:

Post a Comment