直接貼代碼,不解釋
1 主服務,用來偵聽連接埠
package org.javaren.proxy;import java.net.ServerSocket;import java.net.Socket;public class SocketProxy {/** * @param args */public static void main(String[] args) throws Exception {ServerSocket serverSocket = new ServerSocket(8888);while (true) {Socket socket = null;try {socket = serverSocket.accept();new SocketThread(socket).start();} catch (Exception e) {e.printStackTrace();}}}}
2 核心代碼,處理連結的代理線程
內部設計了Socket的認證,自己看吧
package org.javaren.proxy;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;public class SocketThread extends Thread {private Socket socketIn;private InputStream isIn;private OutputStream osIn;//private Socket socketOut;private InputStream isOut;private OutputStream osOut;public SocketThread(Socket socket) {this.socketIn = socket;}private byte[] buffer = new byte[4096];private static final byte[] VER = { 0x5, 0x0 };private static final byte[] CONNECT_OK = { 0x5, 0x0, 0x0, 0x1, 0, 0, 0, 0, 0, 0 };public void run() {try {System.out.println("\n\na client connect " + socketIn.getInetAddress() + ":" + socketIn.getPort());isIn = socketIn.getInputStream();osIn = socketIn.getOutputStream();int len = isIn.read(buffer);System.out.println("< " + bytesToHexString(buffer, 0, len));osIn.write(VER);osIn.flush();System.out.println("> " + bytesToHexString(VER, 0, VER.length));len = isIn.read(buffer);System.out.println("< " + bytesToHexString(buffer, 0, len));// 尋找主機和連接埠String host = findHost(buffer, 4, 7);int port = findPort(buffer, 8, 9);System.out.println("host=" + host + ",port=" + port);socketOut = new Socket(host, port);isOut = socketOut.getInputStream();osOut = socketOut.getOutputStream();//for (int i = 4; i <= 9; i++) {CONNECT_OK[i] = buffer[i];}osIn.write(CONNECT_OK);osIn.flush();System.out.println("> " + bytesToHexString(CONNECT_OK, 0, CONNECT_OK.length));SocketThreadOutput out = new SocketThreadOutput(isIn, osOut);out.start();SocketThreadInput in = new SocketThreadInput(isOut, osIn);in.start();out.join();in.join();} catch (Exception e) {System.out.println("a client leave");} finally {try {if (socketIn != null) {socketIn.close();}} catch (IOException e) {e.printStackTrace();}}System.out.println("socket close");}public static String findHost(byte[] bArray, int begin, int end) {StringBuffer sb = new StringBuffer();for (int i = begin; i <= end; i++) {sb.append(Integer.toString(0xFF & bArray[i]));sb.append(".");}sb.deleteCharAt(sb.length() - 1);return sb.toString();}public static int findPort(byte[] bArray, int begin, int end) {int port = 0;for (int i = begin; i <= end; i++) {port <<= 16;port += bArray[i];}return port;}// 4A 7D EB 69// 74 125 235 105public static final String bytesToHexString(byte[] bArray, int begin, int end) {StringBuffer sb = new StringBuffer(bArray.length);String sTemp;for (int i = begin; i < end; i++) {sTemp = Integer.toHexString(0xFF & bArray[i]);if (sTemp.length() < 2)sb.append(0);sb.append(sTemp.toUpperCase());sb.append(" ");}return sb.toString();}}
3 讀取線程,負責外面讀資料,寫入到請求端
package org.javaren.proxy;/** * * 從外部讀取,向內部發送資訊 */import java.io.InputStream;import java.io.OutputStream;public class SocketThreadInput extends Thread {private InputStream isOut;private OutputStream osIn;public SocketThreadInput(InputStream isOut, OutputStream osIn) {this.isOut = isOut;this.osIn = osIn;}private byte[] buffer = new byte[409600];public void run() {try {int len;while ((len = isOut.read(buffer)) != -1) {if (len > 0) {System.out.println(new String(buffer, 0, len));osIn.write(buffer, 0, len);osIn.flush();}}} catch (Exception e) {System.out.println("SocketThreadInput leave");}}}
4 寫入線程,負責讀取請求端資料,寫入到目標端
package org.javaren.proxy;import java.io.InputStream;import java.io.OutputStream;/** * 從內部讀取,向外部發送資訊 * * @author zxq * */public class SocketThreadOutput extends Thread {private InputStream isIn;private OutputStream osOut;public SocketThreadOutput(InputStream isIn, OutputStream osOut) {this.isIn = isIn;this.osOut = osOut;}private byte[] buffer = new byte[409600];public void run() {try {int len;while ((len = isIn.read(buffer)) != -1) {if (len > 0) {System.out.println(new String(buffer, 0, len));osOut.write(buffer, 0, len);osOut.flush();}}} catch (Exception e) {System.out.println("SocketThreadOutput leave");}}}
效果還不錯,用firefox/ ie都測試過,可用。