1. 程式人生 > 實用技巧 >Java實現http代理伺服器

Java實現http代理伺服器

預設埠:8888

javacRuphyHttpProxy.java

javaRuphyHttpProxy 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(); } } } } }