计算机网络:Socket编程-多线程优化和请求响应对象封装

上篇写了计算机网络:Socket编程-面向对象封装,然后以下基于之前的代码进一步进行多线程优化和请求响应对象封装。

1、多线程优化

对之前面向对象封装的代码,添加多线程优化,代码实现:

package com.hh.http;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;

/**
 * 加入多线程优化
 *
 * @author hang.yuan 2022/3/8 18:50
 */
public class HttpServer3 {

    ServerSocket serverSocket;

    Function<String,String> handler;
    ExecutorService executorService;

    public HttpServer3(Function<String, String> handler) {
        this.handler = handler;
        this.executorService = Executors.newFixedThreadPool(10);
    }

    public void listen(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        while (true){
           this.accept();
        }
    }

    void accept() throws IOException {

        // Blocking ...
        Socket socket = serverSocket.accept();
        // 多线程工作
        executorService.execute(()->{
            try{
                this.handler(socket);
            }catch (IOException e){
                e.printStackTrace();
            }
        });
    }

    public void handler(Socket socket)throws IOException {
        try{

            // Thread --> Sleep --> Other Threads
            System.out.println("socket created");

            InputStream inputStream = new DataInputStream(socket.getInputStream());
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

            StringBuilder requestBuilder = new StringBuilder();

            String line = "";

            while (true){
                line = bufferedReader.readLine();
                if(line ==null || line.isEmpty()){
                    break;
                }
                requestBuilder.append(line+"\n");
            }
            String request = requestBuilder.toString();
            System.out.println(request);

            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            String response = this.handler.apply(request);
            bufferedWriter.write(response);
            bufferedWriter.flush();
            socket.close();
        }catch (IOException e){
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws IOException {
        HttpServer3 server = new HttpServer3(req -> {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "HTTP/1.1 201 ok\n\nGood!\n";
        });

        server.listen(8000);

    }
}

2、Request和Response对象封装

代码进行多线程优化后,进一步对请求(Request)和响应(Response)对象的封装

  • HttpServer对象
package com.hh.http;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;

/**
 * Request/Response 进步抽象
 *
 * @author hang.yuan 2022/3/8 18:50
 */
public class HttpServer31 {

    ServerSocket serverSocket;

    IHandlerInterface handler;
    ExecutorService executorService;

    public HttpServer31(IHandlerInterface handler) {
        this.handler = handler;
        this.executorService = Executors.newFixedThreadPool(5);
    }

    public void listen(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        while (true){
           this.accept();
        }
    }

    void accept() throws IOException {

        // Blocking ...
        Socket socket = serverSocket.accept();

        executorService.execute(()->{
            try{
                this.handler(socket);
            }catch (IOException e){
                e.printStackTrace();
            }
        });
    }

    public void handler(Socket socket)throws IOException {
        Request request = new Request(socket);
        Response response = new Response(socket);
        this.handler.handler(request,response);
    }

    public static void main(String[] args) throws IOException {

        HttpServer31 server = new HttpServer31((req,resp)->{
            System.out.println(req.getHeaders());
            resp.send("<html><body><H1>Hello Word</H1></body></html>");
        });

        server.listen(8000);

    }
}
  • 逻辑处理接口
package com.hh.http;

import java.io.IOException;

/**
 * 接口
 *
 * @author hang.yuan 2022/3/8 20:07
 */
@FunctionalInterface
public interface IHandlerInterface {

    void handler(Request request, Response response) throws IOException;
}
  • Request对象
package com.hh.http;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpParser;

import java.io.*;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 请求
 *
 * @author hang.yuan 2022/3/8 19:21
 */
public class Request {

    static Pattern methodRegex = Pattern.compile("(GET|POST|PUT|DELETE|OPTIONS|TRACE|HEAD)");
    private final String body;
    private final String method;
    private final Map<String, String> headers;

    public Request(Socket socket) throws IOException {

        InputStream inputStream = new DataInputStream(socket.getInputStream());
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

        String methodLine = HttpParser.readLine(inputStream, "UTF-8");
        Matcher matcher = methodRegex.matcher(methodLine);
        matcher.find();
        String method = matcher.group();

        Header[] headers = HttpParser.parseHeaders(inputStream, "UTF-8");
        Map<String,String> map = new HashMap<>();
        for (Header header : headers) {
            map.put(header.getName(),header.getValue());
        }

        BufferedReader bufferedReader1 = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder sb = new StringBuilder();
        char[] buffer = new char[1024];
        while (inputStream.available()>0){
            bufferedReader1.read(buffer);
            sb.append(buffer);
        }
        this.body= sb.toString();
        this.method=method;
        this.headers=map;
    }

    public String getBody() {
        return body;
    }

    public String getMethod() {
        return method;
    }

    public Map<String, String> getHeaders() {
        return headers;
    }
}
  • Response对象
package com.hh.http;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * 响应
 *
 * @author hang.yuan 2022/3/8 19:22
 */
public class Response {

    Socket socket;
    private int status = 200;
    static Map<Integer,String> codeMap;

    public Response(Socket socket) {
        this.socket=socket;
        if (codeMap == null){
            codeMap= new HashMap<>();
            codeMap.put(200,"OK");
        }
    }

    public void send(String msg) throws IOException {
        String resp = "HTTP/1.1 "+this.status+" "+ this.codeMap.get(this.status)+"\n";
        resp += "\n";
        resp += msg;
        this.sendRaw(resp);
    }

    public void sendRaw(String msg) throws IOException {
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bufferedWriter.write(msg);
        bufferedWriter.flush();
        socket.close();

    }
}