1 import java.io.IOException; 2 import java.io.InputStream; 3 import java.io.OutputStream; 4 import java.net.ServerSocket; 5 import java.net.Socket; 6 import java.util.Date; 7 import java.util.HashMap; 8 9 public class SimpleForward { 10 // 服务器 11 private ServerSocket server; 12 // 监听本地端口 13 private int localPort = 1080; 14 // 目标主机地址 15 private String remoteHostAddr = "0.0.0.0"; 16 // 目标主机端口 17 private int remoteHostPort = 8388; 18 // 设置超时时间 30s 19 private static int TIMEOUT = 30; 20 // 客户端列表 用于删除失效连接和超时连接 这里的超时是指长时间没有流量的连接 不是连接超时 21 private static HashMap<Socket, Date> clientList = new HashMap<>(); 22 23 public static void main(String[] args) throws IOException { 24 // new SimpleForward(); 25 new SimpleForward(1234, "127.0.0.1", 1080); 26 } 27 28 public SimpleForward() throws IOException { 29 run(); 30 } 31 32 public SimpleForward(int localPort, String remoteHostAddr, int remoteHostPort) throws IOException { 33 this.localPort = localPort; 34 this.remoteHostAddr = remoteHostAddr; 35 this.remoteHostPort = remoteHostPort; 36 run(); 37 } 38 39 private void run() throws IOException { 40 this.server = new ServerSocket(this.localPort); 41 System.out.println("服务器开启成功"); 42 System.out.println("监听端口 : " + this.localPort); 43 // 自动清除失效连接和超时连接 44 new Thread(new AutoDestroy()).start(); 45 while (true) { 46 Socket socket = server.accept(); 47 // 接收到请求就把socket扔进map,value为刷新时间 48 clientList.put(socket, new Date()); 49 String address = socket.getRemoteSocketAddress().toString(); 50 System.out.println("新连接 : " + address); 51 // 建立与目标主机的连接 52 Socket remoteHost = new Socket(this.remoteHostAddr, this.remoteHostPort); 53 System.out.println("连接地址 : " + this.remoteHostAddr + ":" + this.remoteHostPort); 54 // 端口转发 55 new Thread(new Switch(socket, remoteHost.getInputStream(), socket.getOutputStream())).start(); 56 new Thread(new Switch(socket, socket.getInputStream(), remoteHost.getOutputStream())).start(); 57 } 58 } 59 60 // 用于端口转发 61 private class Switch implements Runnable { 62 private Socket socket; 63 private InputStream in; 64 private OutputStream out; 65 66 Switch(Socket socket, InputStream in, OutputStream out) { 67 this.socket = socket; 68 this.in = in; 69 this.out = out; 70 } 71 72 @Override 73 public void run() { 74 int length = 0; 75 byte[] buffer = new byte[1024]; 76 try { 77 while (!socket.isClosed() && (length = in.read(buffer)) > -1) { 78 clientList.put(socket, new Date()); 79 out.write(buffer, 0, length); 80 } 81 } catch (IOException e) { 82 System.out.println("连接关闭"); 83 } 84 } 85 } 86 87 // 用于清除失效连接和超时连接 88 private class AutoDestroy implements Runnable { 89 90 @Override 91 public void run() { 92 for (Socket socket : clientList.keySet()) { 93 Date lastTime = clientList.get(socket); 94 long time = new Date().getTime() - lastTime.getTime(); 95 if (socket.isClosed() || time / 1000 >= TIMEOUT) { 96 try { 97 clientList.remove(socket); 98 socket.close(); 99 } catch (IOException e) { 100 e.printStackTrace(); 101 } 102 } 103 } 104 } 105 } 106 }
原文:https://www.cnblogs.com/panther1942/p/11109575.html