package com.yc.tomcat;
import java.net.ServerSocket;
import java.net.Socket;
public class MyCatServer {
    
    
    public static void main(String[] args) {
        MyCatServer mcs = new MyCatServer();
        mcs.startServer();
    }
    public void startServer() {
        
        int port = 8080;
        boolean flag = false;
        
        try (ServerSocket ss = new ServerSocket(port)) {
            
            while (!flag) {
                Socket s = ss.accept();
                
                
                Thread t = new Thread(new TaskService(s));
                t.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
            
        }
    }
}
 
 
package com.yc.tomcat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TaskService implements Runnable {
    private Socket socket;
    private InputStream in;
    private OutputStream out;
    private boolean flag;
    private String connection = "close";
    
    public TaskService(Socket socket) {
        this.socket = socket;
        flag = true;
        try {
            in = socket.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
            
            flag = false;
        }
        try {
            out = socket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
            
            flag = false;
        }
    }
    @Override
    public void run() {
        while (flag) {
            
            
            try {
                
                
                HttpServletRequest request = new HttpServletRequest(this.in, socket);
                
                HttpServletResponse response = new HttpServletResponse(request, this.out);
            } catch (Exception e) {
                e.printStackTrace();
                
            } finally {
                
                
                
                if ("close".equals(connection)) {
                    flag = false;
                    if (in != null) {
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (out != null) {
                        try {
                            out.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (socket != null) {
                        try {
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}
 
 
package com.yc.tomcat;
import java.io.File;
import java.io.InputStream;
import java.net.Socket;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
public class HttpServletRequest {
    private InputStream in;
    private Socket socket;
    
    private String method;
    private String requestURL;
    private String requestURI;
    private String contextPath;
    private String queryString;
    private Map<String, String[]> parameterMap = new ConcurrentHashMap<>();
    private String scheme;
    private String protocol;
    private String realPath;
    public HttpServletRequest(InputStream in, Socket socket) {
        this.in = in;
        this.socket = socket;
        
        parseRequest();
    }
    private void parseRequest() {
        String requestInfoString = readFromInpuStream();
        
        if (requestInfoString == null || "".equals(requestInfoString)) {
            throw new RuntimeException("读取输入流异常");
        }
        parseRequestInfoString(requestInfoString);
    }
    
    private void parseRequestInfoString(String requestInfoString) {
        
        StringTokenizer st = new StringTokenizer(requestInfoString);
        this.method = st.nextToken();
        this.requestURI = st.nextToken();
        int questionIndex = this.requestURI.indexOf("?");
        if (questionIndex >= 0) {
            this.queryString = this.requestURI.substring(questionIndex + 1);
            this.requestURI = this.requestURI.substring(0, questionIndex);
        }
        this.protocol = st.nextToken();
        this.scheme = this.protocol.substring(0, this.protocol.indexOf("/"));
        int slashIndex = this.requestURI.indexOf("/", 1);
        if (slashIndex >= 0) {
            this.contextPath = this.requestURI.substring(0, slashIndex);
        } else {
            this.contextPath = this.requestURI;
        }
        this.requestURL = this.scheme + "://" + this.socket.getRemoteSocketAddress() + ":" + this.requestURI;
        
        if (this.queryString != null && this.queryString.length() > 0) {
            String[] ps = this.queryString.split("&");
            for (String s : ps) {
                String[] params = s.split("=");
                this.parameterMap.put(params[0], params[1].split(","));
            }
        }
        this.realPath = System.getProperty("user.dir") + File.separator + "webapps";
    }
    
    private String readFromInpuStream() {
        
        String requestInfoString = null;
        StringBuffer sb = new StringBuffer(100 * 1024);
        int length = -1;
        byte[] bs = new byte[100 * 1024];
        try {
            length = this.in.read(bs);
        } catch (Exception e) {
            e.printStackTrace();
            length = 0;
        }
        
        for (int i = 0; i < length; i++) {
            sb.append((char) bs[i]);
        }
        requestInfoString = sb.toString();
        return requestInfoString;
    }
    public Socket getSocket() {
        return socket;
    }
    public String getContextPath() {
        return contextPath;
    }
    public String getRealPath() {
        return realPath;
    }
    public String getMethod() {
        return method;
    }
    public InputStream getIn() {
        return in;
    }
    public String getRequestURL() {
        return requestURL;
    }
    public String getRequestURI() {
        return requestURI;
    }
    public String getQueryString() {
        return queryString;
    }
    public Map<String, String[]> getParameterMap() {
        return parameterMap;
    }
    public String getScheme() {
        return scheme;
    }
    public String getProtocol() {
        return protocol;
    }
}
 
 
package com.yc.tomcat;
import java.io.*;
public class HttpServletResponse {
    private HttpServletRequest request;
    private OutputStream out;
    public HttpServletResponse(HttpServletRequest request, OutputStream out) {
        this.request = request;
        this.out = out;
        
        outResult();
    }
    
    private void outResult() {
        
        byte[] fileContent = null;
        
        String responseProtocol = null;
        
        String uri = this.request.getRequestURI();
        
        String fileName = this.request.getRealPath() + uri;
        
        File file = new File(fileName);
        if (file.exists() == false) {
            File file404 = new File(this.request.getRealPath(), "404.html");
            fileContent = readFile(file404);
            responseProtocol = get404Protocol(fileContent);
        } else {
            
            fileContent = readFile(file);
            responseProtocol = get200Protocol(fileContent);
        }
        try {
            this.out.write(responseProtocol.getBytes());
            this.out.flush();
            this.out.write(fileContent);
            this.out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (this.out != null) {
                try {
                    this.out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    private String get200Protocol(byte[] fileContent) {
        String uri = this.request.getRequestURI();
        int index = uri.lastIndexOf(".");
        if (index >= 0) {
            index = index + 1;
        }
        String extension = uri.substring(index);
        String pro200 = "";
        
        if ("html".equalsIgnoreCase(extension) || "htm".equalsIgnoreCase(extension)) {
            pro200 = "HTTP/1.1 200\r\n" +
                    "Content-Type: text/html\r\n" +
                    "Content-Length: " + fileContent.length + "\r\n\r\n";
        } else if ("css".equalsIgnoreCase(extension)) {
            pro200 = "HTTP/1.1 200\r\n" +
                    "Content-Type: text/css\r\n" +
                    "Content-Length: " + fileContent.length + "\r\n\r\n";
        } else if ("js".equalsIgnoreCase(extension)) {
            pro200 = "HTTP/1.1 200\r\n" +
                    "Content-Type: text/javascript\r\n" +
                    "Content-Length: " + fileContent.length + "\r\n\r\n";
        } else if ("jpg".equalsIgnoreCase(extension) || "jpeg".equalsIgnoreCase(extension)) {
            pro200 = "HTTP/1.1 200\r\n" +
                    "Content-Type: text/jpeg\r\n" +
                    "Content-Length: " + fileContent.length + "\r\n\r\n";
        }
        return pro200;
    }
    
    private String get404Protocol(byte[] fileContent) {
        
        String pro404 = "HTTP/1.1 404\r\n" +
                "Content-Type: text/html;charset=utf-8\r\n" +
                "Content-Language: zh-CN\r\n" +
                "Content-Length: " + fileContent.length + "\r\n\r\n";
        return pro404;
    }
    
    private byte[] readFile(File file) {
        FileInputStream fin = null;
        
        
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            fin = new FileInputStream(file);
            byte[] bs = new byte[10 * 1024];
            int length = -1;
            while ((length = fin.read(bs, 0, bs.length)) != -1) {
                baos.write(bs, 0, length);
                baos.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fin != null) {
                try {
                    fin.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return baos.toByteArray();
    }
}