Java-based web server work mechanism
A web server is also known as an HTTP server because it communicates with its clients and its customers, and these customers are usually browser. A Java-based web server uses two important classes: java.net.socket and java.net.serversocket, and communicate via HTTP messages. The beginning of this article will discuss HTTP and these two classes, followed, will explain the working mechanism of a simple web server application.
Hypertext Transfer Protocol (HTTP)
The HTTP protocol allows the server and client to receive and transmit data over the Internet. It is a request and response protocol ---- Client Send Request, the server responds to the request. HTTP uses a reliable TCP connection, the default TCP port is 80. The first edition of HTTP is HTTP / 0.9 and then replaced by HTTP / 1.0. The current latest version is HTTP / 1.1, which is defined in the RPC2616 specification document.
This chapter is simple to explain HTTP 1.1, which is still enough for the message sent by the web server application. If you are very interested, you can refer to RFC 2616 documentation.
With HTTP, the client initializes a transaction session by establishing a connection and sending an HTTP request, the server contacts the client or responds to a callback connection to the client. They can be interrupted. For example, when using a web browser, you can stop the file download process on the browser to stop the file download process, and turn off the HTTP connection with this web server.
HTTP request (Requests)
An HTTP Request contains three parts:
Method, URL, Agreement / Version request Baotou Request Headers entity package (Entity Body)
The example gives an example of an HTTP request:
Post / Servlet/default.jsp HTTP / 1.1
Accept: Text / Plain; Text / HTML
Accept-language: EN-GB
Connection: Keep-alive
Host: Localhost
Referr: http://localhost/ch8/senddetails.htm
User-agent: mozilla / 4.0 (compatible; msie 4.01; windows 98)
Content-Length: 33
Content-Type: Application / X-WWW-FORM-URLENCODED
Accept-encoding: Gzip, deflate
Lastname = franks & firstname = michael
The first line of request is Method-Uri-Protocol / Version.
Post / Servlet/default.jsp HTTP / 1.1
The request is the POST method, the later / Servlet/default.jsp represents a URL address, and HTTP / 1.1 represents the version of the protocol.
The HTTP standard specification defines some request methods to use to give each HTTP request. HTTP 1.1 Support 7 Request: GET, POST, HEAD, OPTIONS, PUT, DELETE, and TRACE. GET and POST are the most common ways in Internet applications.
The URI completely specifically indicated an Internet resource. A URI is usually interpreted relative to the root directory of the server. Therefore, it always uses the symbol (/). A URL is actually a URI type. The protocol version represents the version of the HTTP protocol currently being used.
Request Header requests some useful client environments and entity (entity body) information. For example, it can include the length of the language and entity used by the browser. Each request header is separated by the CRLF (Route) sequence. In the previous HTTP request, the entity is a simple line below:
Lastname = franks & firstname = michael
In a typical HTTP request, this entity can easily become longer.
HTTP response (responses)
Similar to the request, an HTTP response also contains three parts:
Protocol-Status Code-Description Responds to the Response Headers entity (Entity Body)
Below is a simple example of HTTP response:
HTTP / 1.1 200 ok
Server: Microsoft-IIS / 4.0
Date: Mon, 3 Jan 1998 13:13:33 GMT
Content-Type: Text / HTML
Last-Modified: Mon, 11 Jan 1998 13:23:42 GMT
Content-Length: 112
Welcome to Brainy Software
body>
html>
The first line of response to the header and the request of the above request are similar. The first line tells us that the agreement is HTTP1.1, and the response request has been successful (200 means success), everything is OK.
In response to the header and the requesting header, some useful information is also included. The response entity is the content of the HTML. The head and entities are also separated by the CRLF sequence.
Socket class
Sockets are an endpoint for a network connection. It enables the application to read and write through the network. By sending and receiving byte streams on the connection, two software programs located in different computers can communicate with each other. In order to send a message to another, you need to know the IP address of the other machine and the socket port number. In Java, a socket is represented by the java.net.socket class.
In order to create a socket, you can use the Socket class constructor to complete. These constructors accept host names and ports:
Public socket (String Host, Int Port)
Host represents a remote computer name or an IP address, Port represents the port number of the remote application. For example, to connect to Yahoo.com at the 80-port, you need to construct the following Socket:
New Socket ("Yahoo.com", 80);
Once you have successfully created an instance of a Socket class, you can use it to send and accept bytes. To send byte streams, you must first call the GetputStream method of the Socket class to get a java.io.outputstream object. To send a text to a remote application, you often construct a java.io.PrintWriter object returned from the OutputStream object. To receive the byte stream connected to the other end, to call the GetInputStream method of the Socket class, the method is returned from java.io.inputstream.
The following block creates a socket, communicating with the local HTTP server (127.0.0.1 representative local), send an HTTP request, and then receives a response from the server. It creates a StringBuffer to save the response and print it to the console. Socket Socket = New Socket ("127.0.0.1", "8080");
OutputStream OS = Socket.getOutputStream ();
Boolean Autoflush = True;
PrintWriter Out = New PrintWriter (socket.getOutputStream (), Autoflush;
BufferedReader in = New BufferedReader
New INPUTSTREAMREADER (Socket.getInputStream ()));
// send an HTTP Request to the Web Server
Out.println ("Get /Index.jsp HTTP / 1.1");
Out.println ("Host: Localhost: 8080);
OUT.PRINTLN ("Connection: Close");
Out.println ();
// read the response
Boolean loop = True;
StringBuffer SB = New StringBuffer (8096);
While (loop) {
IF (in.ready ()) {
INT i = 0;
While (i! = - 1) {
i = in.read ();
Sb.Append ((char) i);
}
Loop = false;
}
Thread.currentthread (). SLEEP (50);
}
// Display the response to the out concele
System.out.println (sb.toString ());
Socket.close ();
To get an exact response from the server, you need to send an HTTP request to follow the HTTP protocol rule. If you read the above "Hypertext Transfer Protocol (HTTP)", you should be able to understand the code that just establishes Socket above.
The ServerSocket class Socket class represents the client's socket. Whenever you want to connect to a remote server app, you have to build a socket. If you want to execute a server application, such as an HTTP service or a program, you need to use a different way. Because your server must have always started idle, it doesn't know when the client tries to connect it. At this time, you need to use the Java.Net.Serversocket class. It implements a server socket. One server Socket will wait for a connection from the client. Once it receives a connection request, it creates a socket instance to handle the problem with client communication. To create a server socket, you can use one of the four ServerSocket class constructors. You need to develop the IP address and port listening of the server socket. Typical, IP addresses If it is 127.0.0.1, it means that the server socket will monitor the local machine. This listened IP address is considered a binding address. Another important attribute of Server Socket is its backlog property, which is the maximum queue length that can be accepted before the Server Socket denied the connection request. One of the constructor of the ServerSocket class is as follows: Public ServerSocket (INT Port, INT Backlog, inetdress "; for this constructor, the binding address must be an instance of java.net.inetaddress. A simple approach is to construct an inetaddres object by calling its static method getByname. This method is a string parameter containing hostname: inetaddress.getbyname ("127.0.0.1"); the following line code constructs a serversocket, which monks the 8080 port of the local machine, and the backlog is set to 1. New ServerSocket (8080, 1, inetaddress.getbyname); once there is a Serversocket instance, you can tell it to wait for the connection request by calling the Accept method. This method only returns when there is a connection request. It returns an instance of the Socket class. This Socket object can send and accept the byte stream from the client application, which is the Socket class that is told in the first section. In fact, Accept is the only way mentioned in this article. Application Application Our web server application is part of the EX01.PYRMont package, including three classes: HTTPSERVER Request Response's entry (static main method) is an Httpserver class. It creates an HTTPSERVER instance to call its AWAIT method. As this method is implied, the AWAIT method waits for an HTTP request in a specified port and processes them, and then sends a response to the client. It keeps waiting until a shutdown command is received. (Command Name AWAIT instead of WAIT is that WAIT is an important way to thread in the System.Object class) Application only only static resource, such as HTML and image files from a specific directory. Dynamic headers (such as dates or cookies are not supported. In the following paragraph, let's take a look at these three classes. The HTTPServer class HTTPServer class represents a web server and serves those static resources found in public static directory web_root and its subdirectory. Web_root initializes: public static final string web_root =
System.getProperty ("user.dir") file.seParetor "Webroot"; this code indicates a Webroot directory that contains static resources, which can be used to test the app. A servlet container can also be found in this directory. To request a static resource, enter the following address or URL: http://machinename: port / staticResource MachineName: port / staticResource MachineName: The computer name or IP address running this application. If your browser is on the same machine, you can use localhost as the machine name. The port is 8080. StaticResource is the requesting folder name, which must be in the web-root directory. If you use the same computer to test the application, you want to send an index.html file to the HTTPServer request, then use the following URL: http: // localhost: 8080 / index.html want to stop the server, you can send a shutdown command. This command is defined by the static shutdown_command variable in the HTTPServer class: private static final string shutdown_command = "/ shutdown"; therefore, to stop the service, you can use the command: http: // localhost: 8080 / shutdown now let us see See the AWAIT method mentioned earlier. A list of procedures below gives an explanation. Listing 1.1. The Httpserver Class' Await MethodPublic Void Await () {ServerSocket Serversocket = NULL;
INT port = 8080;
Try {
Serversocket = New Serversocket (port, 1,
Inetaddress.getbyname ("127.0.0.1"));
}
Catch (IOException E) {
E.PrintStackTrace ();
System.exit (1);
}
// Loop Waiting for a Request
While (! shutdown) {
Socket Socket = NULL;
InputStream INPUT = NULL;
OutputStream output = null;
Try {
Socket = serversocket.accept ();
INPUT = Socket.getinputStream ();
Output = socket.getOutputStream ();
// CREATE Request Object and Parse
Request Request = New Request (INPUT);
Request.parse ();
// CREATE RESPONSE OBJECT
Response response = new response (OUTPUT);
Response.setRequest (Request);
Response.sendStaticResource ();
// Close the socket
Socket.close ();
// Check if the previous Uri is a shutdown command
Shutdown = Request.geturi (). Equals (shutdown_command);
}
Catch (Exception E) {
E.PrintStackTrace ();
CONTINUE;
}
}
} The AWAIT method begins by creating a ServerSocket instance. Then it enters a while loop: serversocket = new serversocket (port, 1, inetaddress.getbyname ("127.0.0.1");
...
// Loop Waiting for a Request
While (! shutdown) {
...
} Socket = ServerSocket.Accept (); After receiving a request, the AWAIT method has obtained java.io.InputStream and Java.io.OutputStream objects from the Socket instance returned from the Accept method. INPUT = Socket.getinputStream ();
Output = socket.getOutputStream (); AWAIT then creates a request object and calls its Parse method to resolve the original HTTP request information. // CREATE Request Object and Parse
Request Request = New Request (INPUT);
Request.Parse (); Next, the AWAIT method creates a response object, using the setRequest method and calls its SendStaticResource method. // CREATE RESPONSE OBJECT
Response response = new response (OUTPUT);
Response.setRequest (Request);
Response.sendStaticResource (); Finally, AWAIT closed this socket. Call the Request's geturi method to check if the HTTP request is a shutdown command. If so, the shutdown variable is set to True, and the program exits the While loop. // Close the socket
Socket.close ();
// Check if the previous Uri is a shutdown command
Shutdown = Request.geturi (). Equals (shutdown_command); The Request class request class represents an HTTP request. Socket Processing the client's communication, returns an InputStream object, and can construct an instance of a Request class by passing the object. The raw data of this HTTP request is obtained by calling the Read method of the InputStream object (RAW DATA). Request has two public methods: Parse and Geturi. The PARSE method explains the original data of the HTTP request. It doesn't do a lot of things - it is only the only information that is only HTTP requests, which is from private method PARSEURI. The Parseuri method saves the URI to the URI variable and then calls the public method geturi to return an HTTP request URI. In order to understand how the Parse and Parseuri methods work, you need to know the internal structure of the HTTP request. This structure is defined in the RFC2616 document. An HTTP request contains three parts:
Request Line Request Baotou (Message Body) Now we are only interested in Request Line for the first part of the HTTP request. A request row started by the method tag, the URI and protocol version requested after the rear root, and finally end by the CRLF character. The elements in the request row are separated by space characters. For example, the requested line of the index.html file requested using the GET method is as follows: get /dex.html http / 1.1 // This is a request line method PARSE to read the entire byte stream from the INPUTSTREAM of Socket, the word stream is The Request object is passed, and then Parse stores these byte streams in a buffer and assembles a StringBuffer object called Request in the buffer. The following list 1.2. Displayed the use of the Parse method: listing 1.2. The Request Class' Parse MethodPublic Void Parse () {// be characterified in {// be character in characters from the socket
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
Request.Append ((char) buffer [j]);
}
System.out.print (Request.toString ());
URI = PARSEURI (Request.toString ());
The Parseuri method gets the URI from the request line. Listing 1.3 shows the use of the Parseuri method. The first and second spaces in the Parseuri reduced request are used to get the URI. Listing 1.3. The Request Class' Parseuri MethodPrivate String Parseuri (String RequestString) {
INT INDEX1, INDEX2;
Index1 = RequestString.indexOf ('');
IF (INDEX1! = -1) {
Index2 = RequestString.indexof ('', INDEX1 1);
IF (Index2> Index1)
Return RequestString.substring (INDEX1 1, INDEX2);
}
Return NULL;
} Response class response represents an HTTP response. Its constructor accepts an OutputStream object, such as: public response (OutputStream output) {
THIS.output = OUTPUT;
} The response object is constructed by the AWAIT method of the HTTPServer class, which is passed to the OutputStream object from Socket. The Response class has two public methods: SetRequest and SendStaticResource. SetRequest method passed an REQUEST object to the Response object. The code in Listing 1.4 shows this: listing 1.4. The response class' setrequest methodpublic void setRequest (required) {this.Request = Request;
} The SendStaticResource method is used to send a static resource, such as an HTML file. Listing 1.5 gives its implementation process: listing 1.5. The response class' sendstaticResource method () THROWS IOEXCEPTION {
BYTE [] bytes = new byte [buffer_size];
FileInputStream Fis = NULL;
Try {
File file = new file (httpserver.web_root, request.geturi ());
IF (file.exiss ()) {
FIS = New FileInputStream (File);
INTCH = fis.read (bytes, 0, buffer_size);
While (ch! = -1) {
Output.write (Bytes, 0, CH);
CH = fis.read (bytes, 0, buffer_size);
}
}
Else {
// File Not Found
String ErrorMessage = "http / 1.1 404 file not found / r / n"
"Content-Type: TEXT / HTML / R / N"
"Content-Length: 23 / R / N"
"/ r / n"
Output.write (ErrorMessage.getBytes ());
}
}
Catch (Exception E) {
// thrown if cannot instantiate a file object
System.out.println (E.TOString ());
}
Finally {
IF (FIS! = NULL)
fis.close ();
}
} The SendStaticResource method is very simple. It first passes the parent path and the sub-path to the File class constructor, which is instantiated to the Java.IO.File class. File file = new file (httpserver.web_root, request.geturi ()); then it checks if the file exists. If there is, the SendStaticResource method constructs a java.io.fileInputStream object by passing the File object. Then call the FileInputStream's Read method to write the byte stream as to OutputStream output. Note that the content of the static resource is also sent to the browser as the original data. IF (file.exiss ()) {
FIS = New FileInputStream (File);
INTCH = fis.read (bytes, 0, buffer_size); while (ch! = -1) {
Output.write (Bytes, 0, CH);
CH = fis.read (bytes, 0, buffer_size);
}
} If this file does not exist, the SendStaticResource method sends an error message to the browser. String ErrorMessage = "http / 1.1 404 file not found / r / n"
"Content-Type: TEXT / HTML / R / N"
"Content-Length: 23 / R / N"
"/ r / n"
Output.write (ErrorMessage.getBytes ()); Compilation and Run Application For compilation and running applications, you first need to decompress the .zip file containing the application of this article. The directory you decompressed becomes Working Directory, which has three subdirectories: SRC /, CLASSES /, and LIB /. To compile the application, you need to enter the following statement in the working directory: javac -d. Src / eX01 / pyrmont / *. Java This -d option parameter writes the result to the current directory, not the SRC / directory. To run an application, enter the following statement in the working directory: Java eX01.pyrmont.httpserver To test your app, open the browser, enter the following URL: http: // localhost: 8080 / index.html You will be able to see the index.html page displayed in your browser, as shown in Figure 1. Figure 1. The Output from The Web Server, you can see the following: get /index.html http / 1.1
Accept: * / *
Accept-language: EN-US
Accept-encoding: Gzip, deflate
User-agent: mozilla / 4.0 (compatible; msie 4.01; windows 98)
Host: Localhost: 8080
Connection: Keep-alive
Get /Images/logo.gif http / 1.1
Accept: * / *
Referr: http: // localhost: 8080 / index.html
Accept-language: EN-US
Accept-encoding: Gzip, deflate
User-agent: mozilla / 4.0 (compatible; msie 4.01; windows 98)
Host: Localhost: 8080
Connection: Keep-Alive Summary Summary In this article, you understand a simple WEB server's work mechanism. The application source code included in this article contains only three classes, but not all are useful. Despite this, it can also be served as a good learning tool. Translated by Willpower, 2003.11.24