遇见tomcat(一)

自己写一个http服务器

在了解tomcat之前,先自己尝试写一个http服务器

什么是http协议

HTTP 协议,全称超文本传输协议(Hypertext Transfer Protocol), 允许web服务器和浏览器通过Internet来发送和接受数据,是一种请求/响应协议。http底层使用TCP来进行通信。目前,http已经迭代到了2.x版本,从最初的0.9、1.0、1.1到现在的2.x,每个迭代都加了很多功能。

在http中,始终都是客户端发起一个请求,服务器接受到请求之后,然后处理逻辑,处理完成之后再发送响应数据,客户端收到响应数据,然后请求结束。在这个过程中,客户端和服务器都可以对建立的连接进行中断操作。

http版本区别

。。。

http请求

一个http协议的请求包含三部分:

  1. 请求的首行
    • 方法 URI 协议/版本
  2. 请求的头部
  3. 主体内容

例子:

POST /rest HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Connection: close
cache-control: no-cache
Postman-Token: b0479ec3-4533-47bf-a354-dc22679f4110
User-Agent: PostmanRuntime/7.6.0
Accept: */*
Host: 127.0.0.1:8080
accept-encoding: gzip, deflate
content-length: 11

key1=value1

http响应

http响应包含三部分:

  1. 协议 状态 状态描述
  2. 响应的头部
  3. 主体内容

例子:

HTTP/1.1 200 ok
Content-Type: application/json

{"msg":"true","code":"0"}

客户端的编写

客户端可以用postman等工具或者自己编写实现,主要发送请求用。

服务端的编写

上面的总结知道了http协议的内容是什么了之后,直接就可以编程去解析协议的内容了,比如可以将请求内容序列化成一个自定义的Request类。

public class MyServer {

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080, 1, InetAddress.getByName("127.0.0.1"));


        while (true) {
            Socket socket = serverSocket.accept();
            System.out.println("connect success! " + socket.getPort());
            threadPool.execute(() -> {
                try {
                    handle(socket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    static ExecutorService threadPool = Executors.newFixedThreadPool(4, Executors.defaultThreadFactory());

    public static void handle(Socket socket) throws IOException {
        InputStream inputStream = socket.getInputStream();
        OutputStream outputStream = socket.getOutputStream();


        Request request = new Request(inputStream);//先处理inputStream
        request.parse();
        //reason: read ECONNRESET'
        System.out.println(request.getHeaders());

        PrintWriter out = new PrintWriter(outputStream, true);//convert chars to bytes stream
        out.println("HTTP/1.1 200 ok");
        out.println("Content-Type: application/json");
        out.println();
        JSONObject response = new JSONObject();
        response.put("code", "0");
        response.put("msg", "true");
        out.println(response.toJSONString());
        out.close();
        socket.close();
    }

    static class Request {
        private InputStream input;
        private String uri;
        private Map<String, String> parameters;
        private Map<String, String> headers;

        Request(InputStream input) {
            this.input = input;
        }

        private void parse() throws IOException {
            BufferedReader in = new BufferedReader(new InputStreamReader(input));

            boolean loop = true;
            StringBuffer sb = new StringBuffer(8096);
            while (loop) {

                if (in.ready()) {
                    char[] buffer = new char[4096];
                    int i = 0;
                    int len = in.read(buffer, 0, buffer.length);
                    sb.append(buffer, 0, len);
                    if (len == -1 || len < 4096)
                        loop = false;
                }
            }

            String requestString = sb.toString();
            uri = parseUri(requestString);
            headers = parseHeaders(requestString);
//            System.out.println(requestString);
            //todo 支持parameter解析
        }

        private String parseUri(String requestString) {
            int index1, index2;
            index1 = requestString.indexOf(' ');
            if (index1 != -1) {
                index2 = requestString.indexOf(' ', index1 + 1);
                if (index2 > index1)
                    return requestString.substring(index1 + 1, index2);
            }
            return null;
        }

        private Map<String, String> parseHeaders(String requestString) {
            HashMap<String, String> map = Maps.newHashMap();
            int index1;
            int index2;
            index1 = requestString.indexOf("\r\n");
            index2 = requestString.indexOf("\r\n", index1 + 2);

            while (index2 - index1 > 1) {
                String str = requestString.substring(index1 + 2, index2);
                String[] strings = str.split(": ");
                if (strings.length >= 2) {
                    map.put(strings[0], strings[1]);
                }
                index1 = index2;
                index2 = requestString.indexOf("\r\n", index1 + 2);
            }

            return map;

        }

        public Map<String, String> getHeaders() {
            return headers;
        }
    }
}

参考

https://www.cnblogs.com/java-chen-hao/p/11316521.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值