Java 網路程式設計 -- Proxy

Java 網路程式

簡介

IP

URL

UDP

TCP

Telnet

WebServer

網頁下載

網路爬蟲

Proxy

瀏覽器

訊息

相關網站

參考文獻

最新修改

簡體版

English

import java.net.*;
import java.io.*;
import java.util.*;
 
class ProxyServer {
  ServerSocket proxySocket = null;
  String  root;
  String[] map ={"mpeg=video/mpeg", "mpg=video/mpeg", "wav=audio/x-wav", "jpg=image/jpeg", 
                 "gif=image/gif", "zip=application/zip", "pdf=application/pdf", "xls=application/vnd.ms-excel", 
                 "ppt=application/vnd.ms-powerpoint", "doc=application/msword", "htm=text/html", 
                 "html=text/html", "css=text/plain", "vbs=text/plain", "js=text/plain", "txt=text/plain", 
                 "java=text/plain"};
  FileWriter log = new FileWriter("WebServer.log", true);
  String serverHost = "proxy.internal";  int serverPort=3128;
 
  public static void main(String args[]) throws Exception {
    setProxy("proxy.internal", "3128");
    int proxyPort = 3128;
    String rootPath = "";
    if (args.length >= 2) proxyPort = Integer.parseInt(args[1]);
    if (args.length >= 1) rootPath = args[0];
    new ProxyServer(proxyPort, rootPath);
  }
 
  public ProxyServer(int pPort, String pRoot) throws IOException {
    proxySocket = new ServerSocket(pPort); // 建立 ServerSocket 物件並佔領 port (預設為 80).
    File rootDir = new File(pRoot);
    root = rootDir.getCanonicalPath();
    System.out.println("port="+pPort+" root="+root);
    run();
  }
 
  public static void setProxy(String pProxy, String pPort) {
    Properties systemSettings = System.getProperties();
    systemSettings.put("proxySet", "true");
    systemSettings.put("proxyHost", pProxy);
    systemSettings.put("proxyPort", pPort);
    System.setProperties(systemSettings);
  }
 
  public void run() {
    try {
      while(true) {
        // 接受瀏覽器的連線。注意: accept() 是一個等待型呼叫,會一直等到有連線進來才完成執行。
        Socket clientSocket = proxySocket.accept();
        ProxySession session = new ProxySession(this, clientSocket);
        session.start();
      }
    } catch (Exception e) { e.printStackTrace(); }
  }
 
  String type(String path) {
    String type="*/*";
    path = path.toLowerCase();
    for (int i=0; i<map.length; i++) {
      String[] tokens = map[i].split("=");
      String ext = tokens[0], mime = tokens[1];
      if (path.endsWith("."+ext)) type = mime;
    }
    return type;
  }
 
  void output(DataOutputStream out, String str) throws Exception {
    out.writeBytes(str+"\r\n");
    System.out.println(str);
  }
}
 
class ProxySession extends Thread {
  ProxyServer proxy;
  Socket clientSocket;
  Socket serverSocket;
  int BUF_SIZE = 40960;
  DataOutputStream clientOut, serverOut;
  DataInputStream clientIn, serverIn;
 
  ProxySession(ProxyServer proxy, Socket clientSocket) throws Exception {
    this.proxy = proxy;
    this.clientSocket = clientSocket;
    clientOut = new DataOutputStream(clientSocket.getOutputStream()); // 取得傳送資料的輸出檔。
    clientIn  = new DataInputStream(clientSocket.getInputStream());   // 取得接收資料的輸入檔。
    serverSocket = new Socket(proxy.serverHost, proxy.serverPort);
    serverOut = new DataOutputStream(serverSocket.getOutputStream()); // 取得傳送資料的輸出檔。
    serverIn  = new DataInputStream(serverSocket.getInputStream());   // 取得接收資料的輸入檔。
  }    
 
  public void run() {
  try {
      System.out.println("begin http session");
    while (true) {
      try {
        String request = request(); // 讀取瀏覽器傳來的請求訊息。
        response();           // 回應訊息給對方的瀏覽器。
        } catch (Exception e) { 
          e.printStackTrace();
          break;
        }
    }
      System.out.println("end http session");
    if (!clientSocket.isClosed()) clientSocket.close();
    if (!serverSocket.isClosed()) serverSocket.close();
  } catch (Exception e) { e.printStackTrace(); }
  }  
 
  String request() throws Exception {
      // read request form client
    String head = readHead(clientIn);
    System.out.println("=========request:head============\r\n"+head);
    byte[] content = readContent(head, clientIn);
      // send request to server
      serverOut.write(head.getBytes("UTF-8"));
    if (content != null) {
        serverOut.write(content);
    }
    return head;
  }
 
  void response() throws Exception {
      // read response form server
    String head = readHead(serverIn);
    System.out.println("=========response:head===========\r\n"+head);
    byte[] content = readContent(head, serverIn);
      // send response to client
      clientOut.write(head.getBytes("UTF-8"));
    if (content != null) {
        clientOut.write(content);
    }
    String proxyConnection=innerText(head, "Proxy-Connection:", "\n");
    System.out.println("proxyConnection="+proxyConnection);
//    if (proxyConnection==null || proxyConnection.toLowerCase().trim().equals("close"))
        throw new Exception("connection close");
  }
 
  public static String innerText(String pText, String beginMark, String endMark) {
    int beginStart = pText.indexOf(beginMark);
    if (beginStart < 0) return null;
    int beginEnd = beginStart+beginMark.length();
    int endStart = pText.indexOf(endMark, beginEnd);
    if (endStart < 0) return null;
    return pText.substring(beginEnd, endStart);
  }
 
  String readHead(DataInputStream in) {
    String head = "";
    try {
      // 讀取到第一個空白行為止,這是標頭訊息。
      while (true) {
        String line = in.readLine();
        if (line == null) break;
        head += line+"\n";
        if (line.length() == 0) break;
      }
    } catch (Exception e) {}
    return head;
  }
 
  byte[] readContent(String head, DataInputStream in) {
    try {
      // 根據 Content-Length: ,讀取到第一個空白行後面的區塊。
      String lengthStr = innerText(head.toLowerCase(), "content-length:", "\n");
      System.out.println("*contentLength:"+lengthStr);
      if (lengthStr != null) {
        int contentLength = Integer.parseInt(lengthStr.trim());
        byte[] content = new byte[contentLength];
        in.read(content);
        return content;
      }
    } catch (Exception e) {}
    return null;
  }
}

Facebook

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License