jmcdonald69124
asked on
HTTP1.1 keep-alive support for simple server
Hello,
I would like to know if anyone can give me an example of how to extend this simple server to allow support for HTTP keep- alive (1.1 only)
import java.io.*;
import java.net.*;
import java.util.*;
public final class WebServer {
public static void main(String args[]) throws Exception {
//Establish the listen socket
int PORT = 777;
ServerSocket listenSocket = new ServerSocket(PORT);
//Process HTTP service requests in an infinite loop
while(true) {
//listen for TCP connection request
//Construct an object to process the HTTP request message
HttpRequest request = new HttpRequest(listenSocket.a ccept());
Thread thread = new Thread(request);
thread.start();
}
}
}
final class HttpRequest implements Runnable {
final static String CRLF ="\r\n";
Socket socket;
public HttpRequest(Socket socket) throws Exception {
this.socket = socket;
}
//Implement the run() method of the Runnable interface
public void run() {
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
private void processRequest() throws Exception {
//Get references to sockets input and output streams
InputStream is = this.socket.getInputStream ();
DataOutputStream os = new DataOutputStream(this.sock et.getOutp utStream() );
//Set up input stream filter
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//Get the request line of HTTP message
String requestLine = br.readLine();
//Make the server directory C:\Webserver
String root_dir;
root_dir = "C:\\Webserver\\";
// Extract the filename from the request line. Assume a GET command
StringTokenizer tokens = new StringTokenizer(requestLin e);
tokens.nextToken();
String fileName = tokens.nextToken();
// Drop the slash at the begginning.
if(fileName.startsWith("/" ))
fileName = root_dir + fileName.substring(1,fileN ame.length ());
// Open the requested file.
FileInputStream fis = null;
boolean fileExists = true;
try {
fis = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
fileExists = false;
}
// Construct the response message.
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if (fileExists) {
statusLine = "HTTP/1.0 200 OK" + CRLF;
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
} else {
statusLine = "HTTP/1.0 404 Not Found" + CRLF;
contentTypeLine = "NONE";
entityBody = "\n\n Sorry The File You Requested Is Not There!!";
}
// Send the status line.
os.writeBytes(statusLine);
// Send the content type line.
os.writeBytes(contentTypeL ine);
// Send a blank line to indicate the end of the header lines.
os.writeBytes(CRLF);
// Send the entity body.
if (fileExists) {
sendBytes(fis, os);
fis.close();
} else {
os.writeBytes(entityBody);
}
//Close the streams
os.close();
br.close();
socket.close();
}
private String contentType(String fileName) {
if(fileName.endsWith(".htm ") || fileName.endsWith(".html") )
return "text/html";
else if(fileName.endsWith(".jpg ") || fileName.endsWith(".jpeg") )
return "image/jpeg";
else if(fileName.endsWith(".gif "))
return "image/gif";
else if(fileName.endsWith(".txt "))
return "text/plain";
else
return "application/octet-stream" ;
}
private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception {
// Construct a 1K buffer to hold bytes on their way to the socket.
byte[] buffer = new byte[1024];
int bytes = 0;
// Copy requested file into the socket's output stream.
while((bytes = fis.read(buffer)) != -1 )
os.write(buffer, 0, bytes);
}
}
I have found several sites on the subject but have not been able to find an in depth example.
Thanks
I would like to know if anyone can give me an example of how to extend this simple server to allow support for HTTP keep- alive (1.1 only)
import java.io.*;
import java.net.*;
import java.util.*;
public final class WebServer {
public static void main(String args[]) throws Exception {
//Establish the listen socket
int PORT = 777;
ServerSocket listenSocket = new ServerSocket(PORT);
//Process HTTP service requests in an infinite loop
while(true) {
//listen for TCP connection request
//Construct an object to process the HTTP request message
HttpRequest request = new HttpRequest(listenSocket.a
Thread thread = new Thread(request);
thread.start();
}
}
}
final class HttpRequest implements Runnable {
final static String CRLF ="\r\n";
Socket socket;
public HttpRequest(Socket socket) throws Exception {
this.socket = socket;
}
//Implement the run() method of the Runnable interface
public void run() {
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
private void processRequest() throws Exception {
//Get references to sockets input and output streams
InputStream is = this.socket.getInputStream
DataOutputStream os = new DataOutputStream(this.sock
//Set up input stream filter
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//Get the request line of HTTP message
String requestLine = br.readLine();
//Make the server directory C:\Webserver
String root_dir;
root_dir = "C:\\Webserver\\";
// Extract the filename from the request line. Assume a GET command
StringTokenizer tokens = new StringTokenizer(requestLin
tokens.nextToken();
String fileName = tokens.nextToken();
// Drop the slash at the begginning.
if(fileName.startsWith("/"
fileName = root_dir + fileName.substring(1,fileN
// Open the requested file.
FileInputStream fis = null;
boolean fileExists = true;
try {
fis = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
fileExists = false;
}
// Construct the response message.
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if (fileExists) {
statusLine = "HTTP/1.0 200 OK" + CRLF;
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
} else {
statusLine = "HTTP/1.0 404 Not Found" + CRLF;
contentTypeLine = "NONE";
entityBody = "\n\n Sorry The File You Requested Is Not There!!";
}
// Send the status line.
os.writeBytes(statusLine);
// Send the content type line.
os.writeBytes(contentTypeL
// Send a blank line to indicate the end of the header lines.
os.writeBytes(CRLF);
// Send the entity body.
if (fileExists) {
sendBytes(fis, os);
fis.close();
} else {
os.writeBytes(entityBody);
}
//Close the streams
os.close();
br.close();
socket.close();
}
private String contentType(String fileName) {
if(fileName.endsWith(".htm
return "text/html";
else if(fileName.endsWith(".jpg
return "image/jpeg";
else if(fileName.endsWith(".gif
return "image/gif";
else if(fileName.endsWith(".txt
return "text/plain";
else
return "application/octet-stream"
}
private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception {
// Construct a 1K buffer to hold bytes on their way to the socket.
byte[] buffer = new byte[1024];
int bytes = 0;
// Copy requested file into the socket's output stream.
while((bytes = fis.read(buffer)) != -1 )
os.write(buffer, 0, bytes);
}
}
I have found several sites on the subject but have not been able to find an in depth example.
Thanks
ignore my comment :)
perhaps have a look at jigsawand see how they handle it:
http://www.w3.org/Jigsaw/
http://www.w3.org/Jigsaw/
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
The changes models the connection to the client as something separate from the request itself. You will need to make changes in the HttpRequest class, or the HttpConnection class to cater for whether keepAlive should be on. Currently the default setting is keepAlive = true.
\t
\t
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
:-)
=-)
Connection: close
You must parse the http request headers to check for such a message from the client.
To keep alive, i.e, to not close the connection, you will have to modify the processRequest() method in your program.
Here, at the end of the method, you are closing the input streams, which essentially closes the socket connection. You must move the contents of this method into an infinite loop. Then try to read the stream using a non-blocking technique...i.e, check the availability of bytes to read. Otherwise sleep for a small time (say 100ms) and check again. Have a time-out of say 60 seconds. i.e, if there has been no activity for some 600 loops, then close the connection.
if the HTTP header requesting not to keep alive is set (Connection: close), then do not go into the loop. Break out after the first iteration.
That is a primitive way of doing things. But given the primitive web server, it should be good enough :-)