Java实现简易Tomcat服务器(清晰易懂)

Tomcat服务器是一个轻量级的Java代码实现的WEB服务器。这篇文章将会讲述如何用Java实现一个简易版的Tomcat服务器。

简单的讲,简易原理是这样的:

1. Tomcat开始运行之后,会在主机上开一个端口(默认是80端口),在所开辟的端口上运行一个ServerSocket,执行accept()方法等待浏览器访问。

2. 浏览器访问目标主机的80端口,ServerSocket的accept()方法返回一个运行在服务器端的socket,该socket有getInputStream()方法和getOutputStream方法,可以获得浏览器对服务器发送的内容和响应浏览器并发送内容。

3. 浏览器收到服务器响应的内容,通过浏览器解释,内容显示在用户眼前。

注意:

1. 浏览器发送给服务器的访问请求符合HTTP协议。

2. 浏览器可以像服务器请求一个HTML页面,也可以请求图片,若HTML页面中导入了图片或者css,js,则这些内容也会像服务器请求,服务器会根据文件名,对浏览器进行响应,若该文件在服务器目录中找不到,则返回404错误。

3. 本简易Tomcat服务器只适用于静态资源。

4. 本简易Tomcat分为两个类,Server类以及Handler类,Server类接收请求,然后创建子线程,到Handler类中去处理浏览器发送的请求,并反馈。

代码及注释如下:

package com.yykj;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) {
        Server server = new Server();
        server.startServer();
    }
    public  void startServer(){
        try {
            ServerSocket serverSocket = new ServerSocket(80);//开启80端口
            System.out.println("服务器启动>>> 80端口");
            while(true){//开启一个永远的循环,一直等待客户访问80端口
                Socket socket = serverSocket.accept();
                Thread thread = new Thread(new Handler(socket));//当有客户访问时,开辟一个新线程处理该请求
                System.out.println("收到新请求");
                thread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Handler类:

package com.yykj;

import java.io.*;
import java.net.Socket;

//请求处理程序
public class Handler implements  Runnable {

    private Socket socket;
    private OutputStream outputStream;
    private InputStream inputStream;
    private BufferedReader reader;
    private PrintWriter writer;
    private static String WEB_ROOT = "C:\\Users\\Administrator\\Desktop\\web";//服务器储存文件目录
    public Handler(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run(){
        try{
            inputStream = socket.getInputStream();//服务器到客户的输出流
            outputStream = socket.getOutputStream();//客户到服务器的输入流
            reader = new BufferedReader(new InputStreamReader(inputStream));//包装后的输入缓冲字符流
            writer = new PrintWriter(new OutputStreamWriter(outputStream));//包装后的输出缓冲字符流
            String msg;//接收客户端请求的临时字符串
            StringBuffer request = new StringBuffer();//将请求拼接成完整的请求
            while((msg = reader.readLine()) != null && msg.length() > 0){
                request.append(msg);
                request.append("\n");//HTTP协议的格式
            }
            String[] msgs = request.toString().split(" ");//HTTP协议以空格为分隔符
            //msgs[1]代表了HTTP协议中的第二个字符串,是浏览器请求的文件名
/*            if(msgs[1].endsWith(".ico")){//.ico文件是浏览器页面的图标文件,是浏览器默认会向服务器发送的请求
                writer.println("HTTP/1.1 200 OK");//如果服务器不打算对客户端发送.ico结尾的文件,可以这一写,然后直接返回,跳过发送该文件的过程
                writer.println("Content-Type: text/html;charset=UTF-8");
                writer.close();
                //如果不发送,就直接返回
                return;
            }*/
            //将服务器目录下被请求的文件读入程序
            FileInputStream fileInputStream = new FileInputStream(new File(WEB_ROOT + msgs[1]));
            byte[] fileBuffer = new byte[1024];//可能是二进制文件,所以需要用byte数组做缓冲
            int length = 0;
            while((length = fileInputStream.read(fileBuffer)) != -1){
                outputStream.write(fileBuffer, 0, length);//向客户端浏览器发送文件
            }
            outputStream.close();
            inputStream.close();
            reader.close();
            fileInputStream.close();
        }catch (IOException e){
            //如果抛出异常,在这里基本上是未找到被请求文件,所以返回404
            writer.write("HTTP/1.1 404 ERROR:FILE NOT FINDED");
            writer.close();
        }
    }
}

你可能感兴趣的:(Java)