IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Socket编程实现HTTP请求 -> 正文阅读

[网络协议]Socket编程实现HTTP请求

一、实现基本功能

package net.test.server;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.function.Function;

/**
 * 进行面向对象的封装和抽象
 * @author 张志伟
 * @version v1.0
 */
public class Step1Server {

    ServerSocket serverSocket;
    Function<String,String> handler;
    public Step1Server(Function<String,String> handler){
        this.handler = handler;
    }
    public void listen(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        while (true){
            this.accept();
        }
    }
    public void accept(){
        try {
            //Blocking
            //Thread -> sleep -> Other Thread
            //阻塞代表当前线程停止执行,sleep,将控制权交给其他线程
            Socket socket = serverSocket.accept();
            System.out.println("A socket created");
            DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(dataInputStream));
            StringBuilder requestBuilder = new StringBuilder();
            String line = "";

            //Readline -> line end '\n'
            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 (SocketException e) {
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        }
    }

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

二、使用多线程进行优化

package net.test.server;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.function.Function;

/**
 * 进行多线程的优化
 * @author 张志伟
 * @version v1.0
 */
public class Step2Server {

    ServerSocket serverSocket;
    Function<String,String> handler;
    public Step2Server(Function<String,String> handler){
        this.handler = handler;
    }
    public void listen(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        while (true){
            this.accept();
        }
    }
    public void accept() throws IOException {
        //Blocking
        //Thread -> sleep -> Other Thread
        //阻塞代表当前线程停止执行,sleep,将控制权交给其他线程
        Socket socket = serverSocket.accept();
        new Thread(() -> {
            try {
                this.handler(socket);
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }).start();
    }
    public void handler(Socket socket){
        try {

            System.out.println("A socket created");
            DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(dataInputStream));
            StringBuilder requestBuilder = new StringBuilder();
            String line = "";

            //Readline -> line end '\n'
            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 (SocketException e) {
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        }
    }

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

三、进行抽象化

package net.test.server;

import java.io.IOException;

/**
 * @author 张志伟
 * @version v1.0
 */
@FunctionalInterface
public interface IHandlerInterface {
    void handler(Request request, Response response) throws IOException;
}

package net.test.server;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 张志伟
 * @version v1.0
 */
public class Request {
    static Pattern methodRegex = Pattern.compile("(GET|PUT|POST|DELETE|OPTIONS|TRACE|HEAD)");
    public String getBody() {
        return body;
    }

    public String getMethod() {
        return method;
    }

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

    private final String body;
    private final String method;
    private final HashMap<String, String> headers;
    public Request(Socket socket) throws IOException {
        DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(dataInputStream));
        //GET /path HTTP/1.1
        String methodLine = bufferedReader.readLine();
        Matcher matcher = methodRegex.matcher(methodLine);
        matcher.find();
        String method = matcher.group();

        // Content-Type:xxxx
        // Length : xxx
        HashMap<String, String> headMap = new HashMap<>();
        String line = "";
        while (true) {
            line = bufferedReader.readLine();
            if (line == null || line.isEmpty()) {
                break;
            }
            String[] split = line.split(":");
            if (split.length == 2){
                headMap.put(split[0],split[1]);
            }else {
                headMap.put(split[0], split[1] + ":" + split[2]);
            }
        }

        StringBuilder body = new StringBuilder();
        char[] buffer = new char[1024];

        while(dataInputStream.available() > 0) {
            bufferedReader.read(buffer);
            body.append(buffer);
        }

        this.body = body.toString();
        this.method = method;
        this.headers = headMap;
    }
}

package net.test.server;

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

/**
 * @author 张志伟
 * @version v1.0
 */
public class Response {
    Socket socket;
    private int status;

    public static volatile HashMap<Integer, String> codeMap;
    public Response(Socket socket) {
        this.socket = socket;
        //双重校验实现单例
        if(codeMap == null) {
            synchronized (Response.class){
                if (codeMap == null){
                    codeMap = new HashMap<>();
                    codeMap.put(200, "OK");
                }
            }

        }
    }
    public void send(String msg) throws IOException {
        String resp = "HTTP/1.1 " + this.status + " " + 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();
    }
}

package net.test.server;

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

/**
 * @author 张志伟
 * @version v1.0
 */
public class Step3Server {
    ServerSocket serverSocket;
    IHandlerInterface httpHandler;
    public Step3Server(IHandlerInterface httpHandler){
        this.httpHandler = httpHandler;
    }
    public void listen(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        while (true){
            this.accept();
        }
    }

    public void accept() throws IOException {
        Socket socket = serverSocket.accept();
        new Thread(()->{
            try {
                this.handler(socket);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }

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

    public static void main(String[] argv) throws IOException {
        Step3Server server = new Step3Server((req, resp) -> {
            System.out.println(req.getHeaders());
            resp.send("<html><body><h1>Hello world!</h1></body></html>");
        });

        server.listen(9999);
    }
}

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-01-30 19:15:44  更:2022-01-30 19:17:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:29:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码