手写简化版tomcat第1课-通过http与socket通讯

学习过tomat源码的人是否有尝试着手写一个简易版的tomcat的冲动呢?其实熟读了tomcat源码的人就应该知道tomcat只是一个强大的socket服务,废话不多说,下面直接贴代码;

一、启动socket监听

public class MyServer {
	public static void main(String[] args) throws IOException {
		// 服务端创建一个监听
        ServerSocket serverSocket = new ServerSocket(9000);
        while(true) {
        	// 监听客户端连接,这里我们暂时没有多线程
            Socket socket = serverSocket.accept();

            // 要想获取客户端发送过来的内容,就要得到 InputStream类 的输入流对象
            InputStream inputStream = socket.getInputStream();

            //==========使用我们自定义的http处理的相关类===========//
            Request request = new Request(inputStream);
            System.out.println(request.readHtml());

            // 要想给客户端发送数据,就要得到
            OutputStream outputStream = socket.getOutputStream();
            Response response = new Response(outputStream);
            response.writeHtml("this is server");

            // 关闭
            inputStream.close();
            outputStream.close();
            socket.close();
        }
        
    }
}

二、将socket的inputStream封装成Request

public class Request {
	// 用来保存输入流对象
    private InputStream inputStream;
    // 从输入流中每次读取的字节长度
    private int bufferLength = 1024;

    /**
     * 构造函数
     * @param inputStream 输入流对象
     */
    public Request(InputStream inputStream){
        this.inputStream = inputStream;
    }

    /**
     * 读取内容
     * @return 返回的是字符串
     * @throws IOException
     */
    public String readHtml() throws IOException {
        // 使用BufferedInputStream对象来读取
        BufferedInputStream bufferedInputStream = new BufferedInputStream(this.inputStream);
        // 每次读取1024字节
        byte[] buffer = new byte[this.bufferLength];

        // 字符串拼接对象
        StringBuilder stringBuilder = new StringBuilder();
        int length = 0;
        while (true){

            length = bufferedInputStream.read(buffer);

            // 把读取的字节转为String类型
            // 然后拼接成一个大的字符串
            stringBuilder.append(new String(buffer,0,length));

            if (length<=0 || length<this.bufferLength){
                break; // 如果没有读取到内容就跳出循环
            }


        }

        // 返回字符串内容
        return stringBuilder.toString();
    }
}

三、将socket的outputStream封装成Response

http的响应数据格式必须遵守http协议

public class Response {
	private OutputStream outputStream;

    public Response(OutputStream outputStream){
        this.outputStream = outputStream;
    }

    public void writeHtml(String html) throws IOException{
        // 拼装http响应的数据格式
        html = "http/1.1 200 ok\n"
                +"\n\n"
                +html;


        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(this.outputStream);
        bufferedOutputStream.write(html.getBytes());
        bufferedOutputStream.close();
    }
}

四、顺便了普及一下http协议

<1>请求头格式
在这里插入图片描述
在这里插入图片描述
<2>响应报文格式
在这里插入图片描述
<3>状态码说明
100~199:表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程。

200~299:表示成功接收请求并已完成整个处理过程。常用200

300~399:为完成请求,客户需进一步细化请求。例如:请求的资源已经移动一个新地址、常用302(意味着你请求我,我让你去找别人),307和304(我不给你这个资源,自己拿缓存)

400~499:客户端的请求有错误,常用404(意味着你请求的资源在web服务器中没有)403(服务器拒绝访问,权限不够)

500~599:服务器端出现错误,常用500

http协议参考资料:https://blog.csdn.net/shouwang666666/article/details/70232053

五、浏览器通过http协议访问服务并返回结果

在浏览器中输入:http://127.0.0.1:9000/
控制台打印请求数据格式
在这里插入图片描述

参考资料:https://blog.csdn.net/github_26672553/article/details/77507797

猜你喜欢

转载自blog.csdn.net/csdnjquery163com/article/details/82897961