java Socket 实现简单的web 服务器

更具体可参见源码注释

web.java
package com.xxx.socket;
import java.io.*;
        import java.util.*;
        import java.net.*;
 
        public class Webserver{
 
                //根资源路径        
                protected String docroot;
 
                //绑定端口,一般采用二级端口:8080
                protected int port;
 
                //监听scoket,监听请求
                protected ServerSocket ss;
 
                //内部类对象,用于处理一次请求
                class Handler extends Thread{
                        protected PrintWriter pw;
                        protected BufferedOutputStream bos;
                        protected BufferedReader br;
                        protected File docroot;  //所请求的资源
                        protected Socket socket; //请求的链接
 
                        public Handler(Socket _socket,String _docroot) throws Exception{
                                this.socket=_socket;
                                this.docroot=new File(_docroot).getCanonicalFile();
                        }
 
                        @Override
                        public void run(){
                                try{
                                        br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
                                        bos=new BufferedOutputStream(socket.getOutputStream());
                                        pw=new PrintWriter(new OutputStreamWriter(bos));
 
                                        String line=br.readLine();        //获得请求命令
 
                                        socket.shutdownInput();                //关闭输入链接,忽略接下来的数据。
 
                                        if(line == null){
                                                socket.close();
                                                return;
                                        }
                                        System.out.println(line);
                                        if(line.toUpperCase().startsWith("GET")){ //标准GET请求
                                                StringTokenizer tokens=new StringTokenizer(line," ?");
                                                tokens.nextToken(); 
                                                String req=tokens.nextToken();  //请求资源的相对路径
                                                System.out.println("reg :"+req);
                                                String name; //请求资源的完整路径
                                                if(req.startsWith("/") || req.startsWith("\\")){
                                                        name=this.docroot+req;
                                                }else{
                                                        name=this.docroot+File.separator+req;
                                                }
                                                System.out.println("name :" +name);
 
                                                File file=new File(name).getCanonicalFile();
 
                                                //保证file的可访问性
                                                if(!file.getAbsolutePath().startsWith(this.docroot.getAbsolutePath())){
                                                        pw.println("HTTP/1.0 403 Forbidden");
                                                        pw.println();
                                                }else if(!file.exists()){
                                                        pw.println("HTTP/1.0 404 File Not Found");
                                                        pw.println();
                                                }else if(!file.canRead()){
                                                        pw.println("HTTP/1.0 403 Forbidden");
                                                        pw.println();
                                                }else if(file.isDirectory()){
                                                        //请求的是文件夹
                                                        sendDir(bos,pw,file,req);
                                                }else{
                                                        //请求的是文件
                                                        sendFile(bos,pw,file.getAbsolutePath());
                                                }
                                        }else{         //我们只实现了GET的请求方式
                                                pw.println("HTTP/1.0 501 Not Implemented");
                                                pw.println();
                                        }
 
                                        pw.flush();
                                        bos.flush();
                                }catch(Exception e){
                                        e.printStackTrace();
                                }
                                try{
                                        socket.close();
                                }catch(Exception x){
                                        x.printStackTrace();
                                }
                        }
 
                        //相应文件的内容到浏览器
                        protected void sendFile(BufferedOutputStream bos,PrintWriter pw,String fileName) throws Exception{
                                try{
                                        BufferedInputStream bis=new BufferedInputStream(new FileInputStream(fileName));
                                        byte [] data= new byte[10*1024];
                                        int read=bis.read(data);
                                        pw.println("HTTP/1.0 200 Okay"); //先返回状态码
                                        pw.println();
                                        pw.flush();
                                        bos.flush();
                                        while(read!=-1){
                                                bos.write(data,0,read);
                                                read=bis.read(data);
                                        }
                                        bos.flush();
                                }catch(Exception ex){
                                        pw.flush();
                                        bos.flush();
                                }
                        }
 
                        //返回文件夹下面的所有资源列表
                        protected void sendDir(BufferedOutputStream bos,PrintWriter pw,File dir,String req) throws Exception{
                                try{
                                        pw.println("HTTP/1.0 200 Okay"); //先返回状态码
                                        pw.println();
                                        pw.flush();
 
                                        pw.print("<html><head><title>Directory of ");
                                        pw.print(req);
                                        pw.print("</title></head><body><h1>Directory of ");
                                        pw.print(req);
                                        pw.println("</h1><table border=\"0\">");
 
                                        File[] contents=dir.listFiles();
 
                                        for(int i=0;i<contents.length;i++){
                                                pw.print("<tr>");
                                                pw.print("<td><a href=\"");
                                                pw.print(req);
                                                pw.print(contents[i].getName());
                                                if(contents[i].isDirectory()){
                                                        pw.print("/");
                                                }
                                                pw.print("\">");
                                                if(contents[i].isDirectory()){
                                                        pw.print("Dir -> ");
                                                }
                                                pw.print(contents[i].getName());
                                                pw.print("</a></td>");
                                                pw.print("</tr>");
                                        }
                                        pw.println("</table></body></html>");
                                        pw.flush();
                                }catch(Exception ex){
                                        pw.flush();
                                        bos.flush();
                                }
                        }
 
                }
                        //解析命令行传来的参数
                        //param1:资源的根目录 param2:监听的端口
                        protected void parseParams(String[] args) throws Exception{
                                                this.docroot="C:\\Users\\Baron\\Pictures";
                                                this.port=Integer.parseInt("8080");
                        }
 
                        //实例化http服务器                
                        public Webserver(String[] args) throws Exception{
                                System.out.println("Check for parameters");
                                //解析参数
                                parseParams(args);
                                System.out.println("starting web server....");
                                //监听链接
                                this.ss=new ServerSocket(this.port);
                                System.out.println("ok");
                                for(;;){
                                        Socket accept=ss.accept();
                                        //响应请求                                
                                        new Handler(accept,docroot).start();
                                }
                        }
 
                        public static void main(String[] args) throws Exception{
                                Webserver demo=new Webserver(args);
                        }
        }