首页 > 编程语言 > 详细

Java实现http代理服务器

时间:2020-12-30 13:34:16      阅读:30      评论:0      收藏:0      [点我收藏+]

 

默认端口:8888

javac RuphyHttpProxy.java

java RuphyHttpProxy 11111

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RuphyHttpProxy extends Thread {
    private final ServerSocket server;
    private final int port;

    public RuphyHttpProxy(int port) throws IOException {
        this.port = port;
        server = new ServerSocket(port);
        System.out.println("代理端口:" + this.port);
    }

    public static void main(String[] args) throws IOException {
        int port = 8888;
        if (args != null && args.length > 0 && args[0].matches("\\d+")) {
            port = Integer.parseInt(args[0]);
        }
        new RuphyHttpProxy(port).start();
    }

    @Override
    public void run() {
        // 线程运行函数
        while (true) {
            try {
                Socket client = server.accept();
                //使用线程处理收到的请求
                new HttpConnectThread(client).start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static class HttpConnectThread extends Thread {

        private Socket client;
        byte clientInputBuffer[] = new byte[1024 * 1024 * 4];

        private int clientReadLength, port = 80;
        private String host = null;
        private Socket server = null;
        private DataInputStream clientInputStream = null; //客户端输入流
        private DataInputStream serverInputStream = null; //服务端输入流
        private DataOutputStream clientOutputStream = null; //客户端输出流
        private DataOutputStream serverOutputStream = null;  //服务端输出流

        public HttpConnectThread(Socket client) {
            this.client = client;
        }

        @Override
        public void run() {

            try {
                clientInputStream = new DataInputStream(client.getInputStream());
                clientOutputStream = new DataOutputStream(client.getOutputStream());
                if (clientInputStream != null && clientOutputStream != null) {
                    clientReadLength = clientInputStream.read(clientInputBuffer, 0, clientInputBuffer.length); // 从客户端读数据
                    if (clientReadLength > 0) { // 读到数据
                        String clientInputString = new String(clientInputBuffer, 0, clientReadLength);
                        if (clientInputString.contains("\n")) {
                            clientInputString = clientInputString.substring(0, clientInputString.indexOf("\n"));
                            System.out.println(clientInputString);
                        }

                        if (clientInputString.contains("CONNECT ")) {
                            Pattern pattern = Pattern.compile("CONNECT ([^ ]+) HTTP/");
                            Matcher matcher = pattern.matcher(clientInputString);
                            if (matcher.find()) {
                                host = matcher.group(1);
                                if (host.contains(":")) {
                                    port = Integer.parseInt(host.substring(host.indexOf(":") + 1));
                                    host = host.substring(0, host.indexOf(":"));
                                }
                            }
                        }

                        if (clientInputString.contains("http://") && clientInputString.contains("HTTP/")) {
                            // 从所读数据中取域名和端口号
                            Pattern pattern = Pattern.compile("http://([^/]+)/");
                            Matcher matcher = pattern.matcher(clientInputString + "/");
                            if (matcher.find()) {
                                host = matcher.group(1);
                                if (host.contains(":")) {
                                    port = Integer.parseInt(host.substring(host.indexOf(":") + 1));
                                    host = host.substring(0, host.indexOf(":"));
                                }
                            }
                        }
                        if (host != null) {
                            server = new Socket(host, port);
                            // 根据读到的域名和端口号建立套接字
                            serverInputStream = new DataInputStream(server.getInputStream());
                            serverOutputStream = new DataOutputStream(server.getOutputStream());
                            if (serverInputStream != null && serverOutputStream != null && server != null) {
                                if (clientInputString.contains("GET ")) {
                                    doGet();
                                }
                                if (clientInputString.contains("CONNECT ")) {
                                    doConnect();
                                }
                                if (clientInputString.contains("POST ")) {
                                    doPost();
                                }
                            }
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                closeAll();
            }
        }

        /**
         * 处理POST请求
         *
         * @throws IOException
         */
        private void doPost() throws IOException {
            write(clientInputBuffer, clientReadLength, serverOutputStream);
            // 建立线程 , 用于从外网读数据 , 并返回给内网
            new HttpChannel(serverInputStream, clientOutputStream).start();
            // 建立线程 , 用于从内网读数据 , 并返回给外网
            new HttpChannel(clientInputStream, serverOutputStream).start();
        }

        /**
         * 写数据
         *
         * @param buf          缓冲区
         * @param length       读取的偏移量
         * @param outputStream 输出流
         * @throws IOException
         */
        private void write(byte[] buf, int length, DataOutputStream outputStream) throws IOException {
            outputStream.write(buf, 0, length);
            outputStream.flush();
        }

        /**
         * 处理连接请求
         *
         * @return
         */
        private void doConnect() throws IOException {
            String ack = "HTTP/1.0 200 Connection established\r\n";
            ack = ack + "Proxy-agent: proxy\r\n\r\n";
            clientOutputStream.write(ack.getBytes());
            clientOutputStream.flush();
            // 建立线程 , 用于从外网读数据 , 并返回给内网
            new HttpChannel(serverInputStream, clientOutputStream).start();
            // 建立线程 , 用于从内网读数据 , 并返回给外网
            new HttpChannel(clientInputStream, serverOutputStream).start();
        }

        /**
         * 处理GET请求
         *
         * @return
         * @throws IOException
         */
        private void doGet() throws IOException {
            write(clientInputBuffer, clientReadLength, serverOutputStream);
            new HttpChannel(serverInputStream, clientOutputStream).start();
        }

        /**
         * 异常关闭所有流
         */
        private void closeAll() {
            if (serverInputStream != null) {
                try {
                    serverInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverOutputStream != null) {
                try {
                    serverOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (server != null) {
                try {
                    server.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (clientInputStream != null) {
                try {
                    clientInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (clientOutputStream != null) {
                try {
                    clientOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (client != null) {
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static class HttpChannel extends Thread {
        private DataInputStream in;
        private DataOutputStream out;

        public HttpChannel(DataInputStream in, DataOutputStream out) {
            this.in = in;
            this.out = out;
        }

        @Override
        public void run() {
            int len;
            byte buf[] = new byte[10240];
            try {
                while ((len = in.read(buf, 0, buf.length)) != -1) {
                    out.write(buf, 0, len);
                    out.flush();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

 

Java实现http代理服务器

原文:https://www.cnblogs.com/muphy/p/14210917.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!