手写一个最迷你的Web服务器

今天我们就仿照Tomcat服务器来手写一个最简单最迷你版的web服务器,仅供学习交流。

 1. 在你windows系统盘的F盘下,创建一个文件夹webroot,用来存放前端代码。
  2. 代码介绍:

      (1)ServerThread.java 核心代码,主要用于web文件的读取与解析等。代码如下:

  1 package server;
  2 
  3 import java.io.*;
  4 import java.net.Socket;
  5 import java.util.Date;
  6 import java.util.HashMap;
  7 import java.util.Map;
  8 
  9 /**
 10  * @ClassName: ServerThread
 11  * @Description:
 12  * @Author: liuhefei
 13  * @Date: 2019/6/23
 14  * @blog: https://www.imooc.com/u/1323320/articles
 15  **/
 16 public class ServerThread implements Runnable {
 17 
 18     private static Map<String, String> contentMap = new HashMap<>();
 19 
 20     //可以参照Tomcat的web.xml配置文件
 21     static {
 22         contentMap.put("html", "text/html");
 23         contentMap.put("htm", "text/html");
 24         contentMap.put("jpg", "image/jpeg");
 25         contentMap.put("jpeg", "image/jpeg");
 26         contentMap.put("gif", "image/gif");
 27         contentMap.put("js", "application/javascript");
 28         contentMap.put("css", "text/css");
 29         contentMap.put("json", "application/json");
 30         contentMap.put("mp3", "audio/mpeg");
 31         contentMap.put("mp4", "video/mp4");
 32     }
 33 
 34     private Socket client;
 35     private InputStream in;
 36     private OutputStream out;
 37     private PrintWriter pw;
 38     private BufferedReader br;
 39 
 40     private static final String webroot = "F:\\webroot\\";    //此处目录,你可以自行修改
 41 
 42     public ServerThread(Socket client){
 43         this.client = client;
 44         init();
 45     }
 46 
 47     private void init(){
 48         //获取输入输出流
 49         try {
 50             in = client.getInputStream();
 51             out = client.getOutputStream();
 52         } catch (IOException e) {
 53             e.printStackTrace();
 54         }
 55 
 56     }
 57 
 58     @Override
 59     public void run() {
 60         try {
 61             gorun();
 62         } catch (Exception e) {
 63             e.printStackTrace();
 64         }
 65     }
 66 
 67     private void gorun() throws Exception {
 68         //读取请求内容
 69         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
 70         String line = reader.readLine().split(" ")[1].replace("/", "\\");  //请求的资源
 71         if(line.equals("\\")){
 72             line += "index.html";
 73         }
 74         System.out.println(line);
 75         String strType = line.substring(line.lastIndexOf(".")+1, line.length());  //获取文件的后缀名
 76         System.out.println("strType = " + strType);
 77 
 78         //给用户响应
 79         PrintWriter pw = new PrintWriter(out);
 80         InputStream input = new FileInputStream(webroot + line);
 81 
 82         //BufferedReader buffer = new BufferedReader(new InputStreamReader(input));
 83         pw.println("HTTP/1.1 200 ok");
 84         pw.println("Content-Type: "+ contentMap.get(strType)  +";charset=utf-8");
 85         pw.println("Content-Length: " + input.available());
 86         pw.println("Server: hello");
 87         pw.println("Date: " + new Date());
 88         pw.println();
 89         pw.flush();
 90 
 91         byte[] bytes = new byte[1024];
 92         int len = 0;
 93         while ((len = input.read(bytes)) != -1){
 94             out.write(bytes, 0, len);
 95         }
 96         pw.flush();
 97 
 98         input.close();
 99         pw.close();
100         reader.close();
101         out.close();
102 
103         client.close();
104     }
105 }
(2)HttpServer.java   (普通版)服务端
 1 package server;
 2 
 3 import java.io.*;
 4 import java.net.ServerSocket;
 5 import java.net.Socket;
 6 import java.util.Date;
 7 
 8 /**
 9  * @ClassName: HttpServer
10  * @Description:  服务端
11  * @Author: liuhefei
12  * @Date: 2019/6/23
13  * @blog: https://www.imooc.com/u/1323320/articles
14  **/
15 public class HttpServer {
16     public static void main(String[] args) throws IOException {
17         //启动服务器,监听9005端口
18         ServerSocket server = new ServerSocket(9005);
19         System.out.println("服务器启动,监听9005端口....");
20         while (!Thread.interrupted()){
21             //不停接收客户端请求
22             Socket client = server.accept();
23             //开启线程
24             new Thread(new ServerThread(client)).start();
25         }
26         server.close();
27     }
28 }

  (2)HttpServer1.java  (线程池版)服务端


 1 package server;
 2 
 3 import java.io.IOException;
 4 import java.net.ServerSocket;
 5 import java.net.Socket;
 6 import java.util.concurrent.ExecutorService;
 7 import java.util.concurrent.Executors;
 8 
 9 /**
10  * @ClassName: HttpServer
11  * @Description:  服务端
12  * @Author: liuhefei
13  * @Date: 2019/6/23
14  * @blog: https://www.imooc.com/u/1323320/articles
15  **/
16 public class HttpServer1 {
17     public static void main(String[] args) throws IOException {
18         //创建线程池
19         ExecutorService pool = Executors.newCachedThreadPool();
20 
21         //启动服务器,监听9005端口
22         ServerSocket server = new ServerSocket(9005);
23         System.out.println("服务器启动,监听9005端口....");
24         while (!Thread.interrupted()){
25             //不停接收客户端请求
26             Socket client = server.accept();
27             //向线程池中提交任务
28             pool.execute(new ServerThread(client));
29         }
30         server.close();
31         pool.shutdown();
32     }
33 }

3. 将一个具有index.html的静态页面文件拷入到我们创建的webroot目录下。相关的静态web资源代码可以到源码之家下载或是自己编写。

4. 启动web服务,启动HttpServer.java 或HttpServer1.java都可以,服务启动之后将会监听9005端口。

5. 我们到浏览器*问我们的服务,访问地址:http://localhost:9005/index.html,

 

 

手写一个最迷你的Web服务器

上一篇:Guideline 2.3.2 - Performance - Accurate Metadata


下一篇:读《大型网站技术架构》的一些总结(2)-获得高可用性