packagenet.rubyeye.concurrency.chapter6;importjava.io.BufferedReader;importjava.io.DataOutputStream;importjava.io.File;importjava.io.FileInputStream;importjava.io.IOException;importjava.io.InputStreamReader;importjava.net.InetAddress;importjava.net.ServerSocket;importjava.net.Socket;publicclassThreadPerTaskWebServer {publicstaticvoidmain(String[] args)throwsIOException {
ServerSocket server=newServerSocket(80);while(true) {finalSocket connection=server.accept();
Runnable task=newRunnable() {publicvoidrun() {try{
handleRequest(connection);
}catch(IOException e) {
e.printStackTrace();
}
}
};newThread(task).start();
}
}publicstaticvoidhandleRequest(Socket socket)throwsIOException {try{
InetAddress client=socket.getInetAddress();//and print it to guis(client.getHostName()+"connected to server.\n");//Read the http request from the client from the socket interface//into a buffer.BufferedReader input=newBufferedReader(newInputStreamReader(
socket.getInputStream()));//Prepare a outputstream from us to the client,//this will be used sending back our response//(header + requested file) to the client.DataOutputStream output=newDataOutputStream(socket
.getOutputStream());//as the name suggest this method handles the http request, see//further down.//abstraction ruleshttp_handler(input, output);
socket.close();
}catch(Exception e) {//catch any errors, and print thems("\nError:"+e.getMessage());
}
}//go back in loop, wait for next request//our implementation of the hypertext transfer protocol//its very basic and stripped downprivatestaticvoidhttp_handler(BufferedReader input,
DataOutputStream output) {intmethod=0;//1 get, 2 head, 0 not supportedString http=newString();//a bunch of strings to holdString path=newString();//the various things, what http v, what//path,String file=newString();//what fileString user_agent=newString();//what user_agenttry{//This is the two types of request we can handle//GET /index.html HTTP/1.0//HEAD /index.html HTTP/1.0String tmp=input.readLine();//read from the streamString tmp2=newString(tmp);
tmp.toUpperCase();//convert it to uppercaseif(tmp.startsWith("GET")) {//compare it is it GETmethod=1;
}//if we set it to method 1if(tmp.startsWith("HEAD")) {//same here is it HEADmethod=2;
}//set method to 2if(method==0) {//not supportedtry{
output.writeBytes(construct_http_header(501,0));
output.close();return;
}catch(Exception e3) {//if some error happened catch its("error:"+e3.getMessage());
}//and display error}//}//tmp contains "GET /index.html HTTP/1.0
."//find first space//find next space//copy whats between minus slash, then you get "index.html"//it's a bit of dirty code, but bear with me
intstart=0;intend=0;for(inta=0; a
end=a;break;
}if(tmp2.charAt(a)==''&&start==0) {
start=a;
}
}
path=tmp2.substring(start+2, end);//fill in the path}catch(Exception e) {
s("errorr"+e.getMessage());
}//catch any exception//path do now have the filename to what to the file it wants to opens("\nClient requested:"+newFile(path).getAbsolutePath()+"\n");
FileInputStream requestedfile=null;try{//NOTE that there are several security consideration when passing//the untrusted string "path" to FileInputStream.//You can access all files the current user has read access to!!!//current user is the user running the javaprogram.//you can do this by passing "../" in the url or specify absoulute//path//or change drive (win)//try to open the file,requestedfile=newFileInputStream(path);
}catch(Exception e) {try{//if you could not open the file send a 404output.writeBytes(construct_http_header(404,0));//close the streamoutput.close();
}catch(Exception e2) {
}
;
s("error"+e.getMessage());
}//print error to gui//happy day scenariotry{inttype_is=0;//find out what the filename ends with,//so you can construct a the right content typeif(path.endsWith(".zip")||path.endsWith(".exe")||path.endsWith(".tar")) {
type_is=3;
}if(path.endsWith(".jpg")||path.endsWith(".jpeg")) {
type_is=1;
}if(path.endsWith(".gif")) {
type_is=2;//write out the header, 200 ->everything is ok we are all//happy.}
output.writeBytes(construct_http_header(200,5));//if it was a HEAD request, we don't print any BODYif(method==1) {//1 is GET 2 is head and skips the bodywhile(true) {//read the file from filestream, and print out through the//client-outputstream on a byte per byte base.intb=requestedfile.read();if(b==-1) {break;//end of file}
output.write(b);
}
}//clean up the files, close open handlesoutput.close();
requestedfile.close();
}catch(Exception e) {
}
}privatestaticvoids(String s) {//System.out.println(s);}//this method makes the HTTP header for the response//the headers job is to tell the browser the result of the request//among if it was successful or not.privatestaticString construct_http_header(intreturn_code,intfile_type) {
String s="HTTP/1.0";//you probably have seen these if you have been surfing the web a whileswitch(return_code) {case200:
s=s+"200 OK";break;case400:
s=s+"400 Bad Request";break;case403:
s=s+"403 Forbidden";break;case404:
s=s+"404 Not Found";break;case500:
s=s+"500 Internal Server Error";break;case501:
s=s+"501 Not Implemented";break;
}
s=s+"\r\n";//other header fields,s=s+"Connection: close\r\n";//we can't handle persistent//connectionss=s+"Server: SimpleHTTPtutorial v0\r\n";//server name//Construct the right Content-Type for the header.//This is so the browser knows what to do with the//file, you may know the browser dosen't look on the file//extension, it is the servers job to let the browser know//what kind of file is being transmitted. You may have experienced//if the server is miss configured it may result in//pictures displayed as text!switch(file_type) {//plenty of types for you to fill incase0:break;case1:
s=s+"Content-Type: image/jpeg\r\n";break;case2:
s=s+"Content-Type: image/gif\r\n";case3:
s=s+"Content-Type: application/x-zip-compressed\r\n";default:
s=s+"Content-Type: text/html\r\n";break;
}so on and so on
s=s+"\r\n";//this marks the end of the httpheader//and the start of the body//ok return our newly created header!returns;
}
}