Simple HTTP Server Implementation (JAVA)

Source: Internet
Author: User
Tags sha1

The simple Java EE Web container lacks many features, but it can provide you with an overview of the HTTP container flow.

Note: container function is very small, only for learning.

1. Supports static content and servlet, does not support JSP

2. Support only 304/404

3. The Design Reference jetty container

Git address: https://git.oschina.net/redcode/jerry.git

First, the HTTP request processing process:

HTTP packet parsing is directly using the socket to read the InputStream, and then read the HTTP request header to the data body according to the HTTP protocol, the HTTP GET request header resembles the following:

Get/http/1.1accept: */*accept-language:zh-cnuser-agent:accept-encoding:gzip, DeflateHost:www.baidu.comConnection : keep-alive

1. If the get/http/1.1 representative is a GET request, the request path is/, the protocol version is HTTP 1.1, the middle is separated by a space, the request header each property row, using \ n newline (Windows is \ r \ n).

When parsing the inputstream of the socket, first read the first line, the code is similar to the following:

Newnew= br.readline (); if NULL {    returnnull= Reqcmd.split ("\\s");

2. the POST request package resembles the following:

post/login http/1.1accept: */*user-agent:host:pragma:no-cachecookie:content-length:25count=1 &viewid=LNE3TRPYVJ

Wrap the request header, then encapsulate the POST request data: COUNT=1&VIEWID0=LNE3TRPYVJ

When the POST request packet is parsed, the request header is read before the data is read and stored in the map. Check the request type as follows:

// Request Method Check if (! Httpmethod.isaccept (cmds[0])) {    returnnull;}

The accepted request type enumeration:

 Public enumHttpMethod {GET, POST;  Public Static Booleanisaccept (String method) { for(HttpMethod m:httpmethod.values ()) {if(M.name (). Equals (method)) {return true; }        }        return false; }         Public StaticHttpMethod GetMethod (String method) { for(HttpMethod m:httpmethod.values ()) {if(M.name (). Equals (method)) {returnm; }        }        return NULL; }}

The POST request needs to read the Content-length property, that is, to know the size of the parameter packet in the post package, and when the TCP packet is split over several links to the destination, the packet length allows the server to reasonably wait for the data to arrive.

//Read HeadersString Line;intContentLength = 0; HashMap<String,String> headers =NewHashmap<string, string>(); while(line = Br.readline ())! =NULL&&!line.equals ("") ) {        intIDX = Line.indexof (":"); if(idx = =-1) {        Continue; }    if(HttpHeaders.CONTENT_LENGTH.equals (line)) {ContentLength= Integer.parseint (line.substring (idx+2). Trim ()); } headers.put (Line.substring (0, IDX), line.substring (idx+2));}

Second, the overall design description:

1. start with the main function to illustrate the design method that should be used, and some mechanisms can be applied to other software designs.

The deployment structure is as follows:

%home%/lib/*----Dependency Packages

%home%/conf/*-----Configuration Folder

%home%/startup.sh---Start the shell

%home%/logs/*----Log Folder

%home%/webapps/*----Page Deployment path

This design method is very similar to Tomcat. The eclipse package structure is as follows:

Project Start class Org.mike.jerry.launcher.Main

Lib class loader Org.mike.jerry.launcher.ClassPath

The service loads the class Org.mike.jerry.launcher.Bootstrap, which reads the configuration and initiates the service port listener.

The configuration file conf/config.properties the default configuration of port 80 and can be accessed using http://127.0.0.1 after startup.

2. request acceptance with thread pool

The real processing request is org.mike.jerry.server.SocketConnector, starting and accepting the request:

protectedServerSocket Newserversocket (String host,intPortintBacklogthrowsioexception{ServerSocket SS= host==NULL?NewServerSocket (port,backlog):NewServerSocket (Port,backlog,inetaddress.getbyname (host)); returnSS; }     Public voidAccept ()throwsIOException {log.info ("Server started ...");  while(started) {Socket socket=serversocket.accept (); Connectorendpoint connector=Newconnectorendpoint (socket);        Connector.dispatch (); }    }

Each request opens a Connectorendpoint thread processing, which is fetched from the thread pool (org.mike.jerry.server.util.thread.ThreadPool), and is handled as follows:

/*Request Handler*/protected classConnectorendpointextendsSocketendpointImplementsRunnable { PublicConnectorendpoint (Socket socket)throwsIOException {Super(socket); Socket.setsotimeout (7000); }                 Public voidDispatch () {Threadpool.dispatch ( This); } @Override Public voidrun () {...}}

3. HTTP Packet Parser

The HTTP packet parsing class is operated by Org.mike.jerry.http.HttpRequestDecoder and HTTP request processing is in the Org.mike.jerry.http package.

The request parsing work has several points:

1. Read the request header, differentiate the Get POST, get the request header property, get read the symbol in the URL "?" And parse the parameters, post needs to read the request parameters in the request body according to Content-length.

The parsed data is stored in the request, and according to the servlet design specification, the request needs to be put into servletinputstream in for the container consumer to be able to read the InputStream in the servlet.

2. After the request has been read, Resuqet and Resourcehandler are processed to read the requested resources.

4. Read Resources

In the read of the resource, the default request is/will be fixed read/index.html file, this property should be configured in Web. XML, but to learn simple, hard coded here.

1. First check if the path matches in the servlet, and if not, proceed to the next step.

2. Read the requested file from the WebApps folder, or return 404 if it does not exist, and then proceed to the next step if it exists.

3. Read the ETag code in the request, this flag is similar to MD5, SHA1 and other file summary, used to change the flag file, if not changed, then return 304, Save the server resources (CPU, disk and network, etc.)

, only MD5 and SHA1 calculate the file digest requires a longer CPU cycle, fixed calculation method is as follows:

 PublicString Getweaketag () {Try{StringBuilder b=NewStringBuilder (32); B.append ("M/\" "); intLength=uri.length (); LongLhash=0;  for(inti=0; i<length;i++) Lhash= 31*lhash +Uri.charat (i); B64code.encode (file.lastmodified ()^Lhash, B); B64code.encode (Length^Lhash, B); B.append (‘"‘); returnb.tostring (); } Catch(IOException e) {Throw NewRuntimeException (e); }    }

5. If the file changes, read the file byte stream again and put it in the response packet response.

-----------------to Be Continued-------------------

Simple HTTP Server Implementation (JAVA)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.