Java實現tcp內網穿透,將內網映射到外網訪問
本文連接:https://www.cnblogs.com/muphy/p/15292965.html
gitee: https://gitee.com/muphy1112/ruphy-frp/
原理如下
為什么需要客戶端和服務端?
服務端先啟動,然后啟動客戶端,
ProxyServer服務端被動等待ProxyClient內網客戶端和外網應用的連接
ProxyClient客戶端主動連接ProxyServer服務端和內網應用的連接,ProxyClient可以代理內網任意主機的TCP應用
使用方法
使用Javac編譯:
javac ProxyServer.java -encoding UTF-8 javac ProxyClient.java -encoding UTF-8
編譯后分別啟動ProxyServer和ProxyClient,此代碼長連接只支持一對一
java ProxyServer 48981 48982 usage: java ProxyServer [內網:6010] [外網:6011] 內網端口:48981,外網端口:48982
java ProxyClient 47.*.*.* 48981 localhost 8080 usage: java ProxyClient [外網:localhost 6011] [內網:localhost 8080] 應用:192.168.2.15:8080,外網:47.*.*.*:48981
源碼:ProxyServer.java
import java.io.*; import java.math.BigInteger; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.Executors; import java.util.regex.Pattern; public class ProxyServer extends Thread { private final ServerSocket intranetServer; private final ServerSocket extranetServer; private static InputStream intranetInputStream = null; //服務端輸入流 private static OutputStream intranetOutputStream = null; //服務端輸出流 //使用線程處理收到的請求 private volatile InputStream extranetInputStream = null; private volatile OutputStream extranetOutputStream = null; private volatile Socket extranetClient = null; private volatile Socket intranetClient = null; public ProxyServer(int intranetPort, int extranetPort) throws IOException { intranetServer = new ServerSocket(intranetPort); extranetServer = new ServerSocket(extranetPort); System.out.println("內網端口:" + intranetPort + ",外網端口:" + extranetPort); } public static void main(String[] args) throws IOException { System.out.println("usage: java ProxyServer [內網:6010] [外網:6011]"); int intranetPort = 6011; int extranetPort = 6010; if (args.length > 0) { intranetPort = Integer.parseInt(args[0]); } if (args.length > 1) { extranetPort = Integer.parseInt(args[1]); } new ProxyServer(intranetPort, extranetPort).start(); } @Override public void run() { // 線程運行函數 if (!getIntranetClient()) { System.out.println("等待內網服務連接失敗"); return; } Executors.newFixedThreadPool(1).execute(() -> { while (true) { if (intranetClient == null || intranetClient.isClosed()) { if (!getIntranetClient()) { System.out.println("等待內網服務連接失敗"); break; } } byte[] buf = new byte[1024]; //try { while (true) { int len = 0; try { len = intranetInputStream.read(buf, 0, buf.length); } catch (IOException e) { e.printStackTrace(); close(intranetInputStream, intranetOutputStream, intranetClient); intranetClient = null; break; } if (len < 0) { close(intranetInputStream, intranetOutputStream, intranetClient); intranetClient = null; break; } String suitableString = getSuitableString(buf, len); System.out.println("內網:" + suitableString); if (extranetClient == null || extranetClient.isClosed()) { continue; } if ("close".equals(suitableString)) { close(extranetInputStream, extranetOutputStream, extranetClient); extranetClient = null; continue; } boolean close = suitableString.endsWith("close"); if (close) { try { extranetOutputStream.write(buf, 0, len - 5); extranetOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } finally { close(extranetInputStream, extranetOutputStream, extranetClient); extranetClient = null; continue; } } try { extranetOutputStream.write(buf, 0, len); extranetOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); close(extranetInputStream, extranetOutputStream, extranetClient); byte[] bytes = "close".getBytes(); try { intranetOutputStream.write(bytes, 0, bytes.length); intranetOutputStream.flush(); } catch (IOException ex) { ex.printStackTrace(); close(intranetInputStream, intranetOutputStream, intranetClient); break; } } } } }); while (true) { byte[] buf = new byte[1024]; try { extranetClient = extranetServer.accept(); System.out.println("外網連接:" + extranetClient.getRemoteSocketAddress()); //使用線程處理收到的請求 extranetInputStream = extranetClient.getInputStream(); //客戶端輸入流 extranetOutputStream = extranetClient.getOutputStream(); //客戶端輸出流 int len; while ((len = extranetInputStream.read(buf, 0, buf.length)) > -1) { System.out.println("外網:" + getSuitableString(buf, len)); intranetOutputStream.write(buf, 0, len); intranetOutputStream.flush(); } } catch (Exception e) { e.printStackTrace(); } close(extranetClient, extranetInputStream, extranetOutputStream); byte[] bytes = "close".getBytes(); try { intranetOutputStream.write(bytes, 0, bytes.length); intranetOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } } } private synchronized boolean getIntranetClient() { if (intranetClient != null && !intranetClient.isClosed()) { return false; } try { intranetClient = intranetServer.accept(); System.out.println("內網連接:" + intranetClient.getRemoteSocketAddress()); intranetInputStream = intranetClient.getInputStream(); intranetOutputStream = intranetClient.getOutputStream(); return true; } catch (IOException e) { e.printStackTrace(); close(intranetInputStream, intranetOutputStream, intranetClient); } return false; } public static String getSuitableString(byte[] bytes, int len) { if (bytes == null || bytes.length == 0) { return ""; } byte[] buffer = new byte[len]; System.arraycopy(bytes, 0, buffer, 0, len); String suitableParseString = new String(buffer);return suitableParseString; } /** * 關閉所有流 */ private static void close(Closeable... closeables) { if (closeables != null) { for (int i = 0; i < closeables.length; i++) { if (closeables[i] != null) { try { closeables[i].close(); } catch (IOException e) { e.printStackTrace(); } } } } } }
源碼:ProxyClient.java
import java.io.*; import java.math.BigInteger; import java.net.InetSocketAddress; import java.net.Socket; import java.util.concurrent.Executors; import java.util.regex.Pattern; public class ProxyClient extends Thread { private Socket server = null; private final String serverIp; private final int serverPort; private Socket app = null; private static InputStream serverInputStream = null; //服務端輸入流 private static OutputStream serverOutputStream = null; //服務端輸出流 private static InputStream appInputStream = null; //服務端輸入流 private static OutputStream appOutputStream = null; //服務端輸出流 private final String appIp; private final int appPort; public ProxyClient(String serverIp, int serverPort, String appIp, int appPort) throws IOException { this.appIp = appIp; this.appPort = appPort; this.serverIp = serverIp; this.serverPort = serverPort; System.out.println("應用:" + appIp + ":" + appPort + ",外網:" + serverIp + ":" + serverPort); } public static void main(String[] args) throws IOException { System.out.println("usage: java ProxyClient [外網:localhost 6010] [內網:localhost 8080]"); String serverIp = "47.*.*.*"; int serverPort = 6011; String appIp = "192.168.2.100"; int appPort = 8080; if (args.length > 0) { serverIp = args[0]; } if (args.length > 1) { serverPort = Integer.parseInt(args[1]); } if (args.length > 2) { appIp = args[2]; } if (args.length > 3) { appPort = Integer.parseInt(args[3]); } new ProxyClient(serverIp, serverPort, appIp, appPort).start(); } @Override public void run() { // 線程運行函數 if (!getServer()) { System.out.println("連接服務器失敗!"); return; } Executors.newFixedThreadPool(1).execute(() -> { while (true) { if (server == null || server.isClosed()) { if (!getServer()) { System.out.println("連接服務器失敗!"); return; } } byte[] buf = new byte[1024]; int len; while (true) { try { len = serverInputStream.read(buf, 0, buf.length); } catch (IOException e) { e.printStackTrace(); close(serverInputStream, serverOutputStream, server); server = null; break; } if (len < 0) { close(serverInputStream, serverOutputStream, server); server = null; break; } String suitableString = getSuitableString(buf, len); System.out.println("外網:" + suitableString); if ("close".equals(suitableString)) { close(appInputStream, appOutputStream, app); app = null; continue; } if (app == null || app.isClosed()) { if (!getApp()) { System.out.println("連接內網應用失敗!"); } } boolean close = suitableString.endsWith("close"); if (close) { try { appOutputStream.write(buf, 0, len - 5); appOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } close(appInputStream, appOutputStream, app); app = null; continue; } try { appOutputStream.write(buf, 0, len); appOutputStream.flush(); } catch (Exception e) { e.printStackTrace(); close(appInputStream, appOutputStream, app); app = null; byte[] bytes = "close".getBytes(); try { serverOutputStream.write(bytes, 0, bytes.length); serverOutputStream.flush(); } catch (IOException ex) { ex.printStackTrace(); close(serverInputStream, serverOutputStream, server); break; } } } } }); } private boolean getServer() { try { server = new Socket(); server.connect(new InetSocketAddress(serverIp, serverPort), 2000); System.out.println("外網服務器連接成功:" + serverIp + ":" + serverPort); serverInputStream = server.getInputStream(); serverOutputStream = server.getOutputStream(); return true; } catch (IOException e) { e.printStackTrace(); } close(serverInputStream, serverOutputStream, server); System.exit(0); return false; } private boolean getApp() { app = new Socket(); try { app.connect(new InetSocketAddress(this.appIp, this.appPort), 2000); appInputStream = new DataInputStream(app.getInputStream()); appOutputStream = new DataOutputStream(app.getOutputStream()); System.out.println("外網服務器連接成功:" + this.appIp + ":" + this.appPort); } catch (IOException e) { app = null; e.printStackTrace(); close(appInputStream, appOutputStream, app); byte[] bytes = "close".getBytes(); try { serverOutputStream.write(bytes, 0, bytes.length); serverOutputStream.flush(); } catch (IOException ex) { ex.printStackTrace(); close(serverInputStream, serverOutputStream, server); server = null; } return false; } Executors.newFixedThreadPool(1).execute(() -> { int len; byte[] buf = new byte[1024]; try { while ((len = appInputStream.read(buf, 0, buf.length)) > -1) { System.out.println("應用:" + getSuitableString(buf, len)); serverOutputStream.write(buf, 0, len); serverOutputStream.flush(); } } catch (Exception e) { e.printStackTrace(); } finally { close(appInputStream, appOutputStream, app); byte[] bytes = "close".getBytes(); try { serverOutputStream.write(bytes, 0, bytes.length); serverOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); close(serverInputStream, serverOutputStream, server); server = null; } } }); return true; } public static String getSuitableString(byte[] bytes) { return getSuitableString(bytes, bytes.length); } public static String getSuitableString(byte[] bytes, int len) { if (bytes == null || bytes.length == 0) { return ""; } byte[] buffer = new byte[len]; System.arraycopy(bytes, 0, buffer, 0, len); String suitableParseString = new String(buffer);return suitableParseString; }/** * 關閉所有流 */ private static void close(Closeable... closeables) { if (closeables != null) { for (int i = 0; i < closeables.length; i++) { if (closeables[i] != null) { try { closeables[i].close(); } catch (IOException e) { e.printStackTrace(); } } } } } }