Sunday, August 1, 2010

Single-threaded HTTP Server

An HTTP Server is an application layer process which accepts and responds to client requests for web objects (pages, images, videos etc.). To explain the process in simple terms, I have included the source code for a basic single threaded server.

HTTP Server
This server will establish TCP connection with the requesting clients. Once done, it can accept "GET" HTTP messages from these clients. The server processes it (parses the request message to extract the file url). This server can accept only jpg and gif file requests. If the file is found in the server, an HTTP response message is generated and send back to the client. After this, the server closes the connection with the client.

Implementation Details
The server is an HTTP 1.0 implementation for it works on non-persistent connection to send and receive data.

I have attached the source code below. You can also access it from here.


/*
* Coded by: Rahul Krishnan
* Description:
* A basic single threaded HTTP server program. It can accept
* GET messages from the clients requesting for jpg and gif
* files. The server then sends the response as HTTP packets.
*/

import java.net.*;
import java.io.*;
import java.util.*;

class WebServer {
public static void main(String argv[]) throws Exception {
String httpReqMsg; // Strores the request from client.
String fileName; // Stores the file name to be fetched.

ServerSocket listenSocket = new ServerSocket(4444);
Socket connectionSocket = listenSocket.accept();

BufferedReader inFromClient = new BufferedReader(
new InputStreamReader(connectionSocket.getInputStream()));

DataOutputStream outToClient = new DataOutputStream(
connectionSocket.getOutputStream());

// Read the request from client.
httpReqMsg = inFromClient.readLine();

StringTokenizer tokenizedLine = new StringTokenizer(httpReqMsg);

// Extract the file name.
if (tokenizedLine.nextToken().equals("GET")) {
fileName = tokenizedLine.nextToken();

// Process the file name.
if (fileName.startsWith("/") == true) {
// Extract the portion after '/' in the file name.
fileName = fileName.substring(1);
}

// Access the file.
File file = new File(fileName);
int numOfBytes = (int) file.length();

byte[] fileInBytes = new byte[numOfBytes];
FileInputStream inFile = new FileInputStream(fileName);

inFile.read(fileInBytes);

// Server response message starts.
outToClient.writeBytes("HTTP/1.0 200 OK\r\n");

// Send the content type.
if (fileName.endsWith(".jpg")) {
outToClient.writeBytes("Content-Type: image/jpeg\r\n");
}
if (fileName.endsWith(".gif")) {
outToClient.writeBytes("Content-Type: image/gif\r\n");
}
// Send the content length.
outToClient.writeBytes("Content-Lenght: " + numOfBytes + "\r\n");

// Important : comply with the HTTP reply format.
outToClient.writeBytes("\r\n");
// Write the file into the output stream.
outToClient.write(fileInBytes, 0, numOfBytes);
connectionSocket.close();
}
else System.out.println("Bad Request Message");
}
}

No comments:

Post a Comment