Java端口转发案例

wen java案例 3

本文目录导读:

Java端口转发案例

  1. 基础版:单线程端口转发
  2. 完整版:支持TCP和UDP转发
  3. 高级版:带SSL支持和流量统计
  4. 使用示例
  5. 命令行使用方式
  6. Maven依赖
  7. 关键特性说明

我来提供一个完整的Java端口转发实现案例,包含多种实现方式。

基础版:单线程端口转发

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class SimplePortForwarder {
    private final String remoteHost;
    private final int remotePort;
    private final int localPort;
    public SimplePortForwarder(String remoteHost, int remotePort, int localPort) {
        this.remoteHost = remoteHost;
        this.remotePort = remotePort;
        this.localPort = localPort;
    }
    public void start() throws IOException {
        ServerSocket serverSocket = new ServerSocket(localPort);
        System.out.println("端口转发启动: localhost:" + localPort + " -> " + remoteHost + ":" + remotePort);
        while (true) {
            Socket clientSocket = serverSocket.accept();
            new Thread(() -> handleConnection(clientSocket)).start();
        }
    }
    private void handleConnection(Socket clientSocket) {
        try {
            // 连接到远程服务器
            Socket remoteSocket = new Socket(remoteHost, remotePort);
            // 创建两个方向的转发线程
            Thread t1 = new Thread(() -> forward(clientSocket, remoteSocket));
            Thread t2 = new Thread(() -> forward(remoteSocket, clientSocket));
            t1.start();
            t2.start();
            // 等待两个线程结束
            t1.join();
            t2.join();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    private void forward(Socket source, Socket target) {
        try (InputStream in = source.getInputStream();
             OutputStream out = target.getOutputStream()) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
                out.flush();
            }
        } catch (IOException e) {
            // 连接关闭是正常情况
        }
    }
    public static void main(String[] args) {
        if (args.length < 3) {
            System.out.println("Usage: java SimplePortForwarder <remoteHost> <remotePort> <localPort>");
            return;
        }
        String remoteHost = args[0];
        int remotePort = Integer.parseInt(args[1]);
        int localPort = Integer.parseInt(args[2]);
        SimplePortForwarder forwarder = new SimplePortForwarder(remoteHost, remotePort, localPort);
        try {
            forwarder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

完整版:支持TCP和UDP转发

import java.io.IOException;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class AdvancedPortForwarder {
    private static final int TCP_BUFFER_SIZE = 65536;
    private static final int UDP_BUFFER_SIZE = 65536;
    private static final int DEFAULT_THREAD_POOL_SIZE = 200;
    private final ExecutorService executorService;
    private final AtomicInteger activeConnections = new AtomicInteger(0);
    public AdvancedPortForwarder() {
        this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE);
    }
    /**
     * TCP转发线程类
     */
    private class TCPForwarder implements Runnable {
        private final Socket clientSocket;
        private final String remoteHost;
        private final int remotePort;
        public TCPForwarder(Socket clientSocket, String remoteHost, int remotePort) {
            this.clientSocket = clientSocket;
            this.remoteHost = remoteHost;
            this.remotePort = remotePort;
        }
        @Override
        public void run() {
            activeConnections.incrementAndGet();
            Socket remoteSocket = null;
            try {
                remoteSocket = new Socket();
                remoteSocket.connect(new InetSocketAddress(remoteHost, remotePort), 30000);
                // 设置TCP优化参数
                clientSocket.setTcpNoDelay(true);
                remoteSocket.setTcpNoDelay(true);
                clientSocket.setKeepAlive(true);
                remoteSocket.setKeepAlive(true);
                // 创建双向转发
                Thread clientToRemoteThread = new Thread(() -> {
                    forwardData(clientSocket, remoteSocket);
                }, "ClientToRemote-" + clientSocket.getPort());
                Thread remoteToClientThread = new Thread(() -> {
                    forwardData(remoteSocket, clientSocket);
                }, "RemoteToClient-" + clientSocket.getPort());
                clientToRemoteThread.start();
                remoteToClientThread.start();
                clientToRemoteThread.join();
                remoteToClientThread.join();
            } catch (IOException | InterruptedException e) {
                // 连接异常或中断,关闭连接
            } finally {
                cleanup(clientSocket);
                cleanup(remoteSocket);
                activeConnections.decrementAndGet();
            }
        }
        private void forwardData(Socket source, Socket target) {
            byte[] buffer = new byte[TCP_BUFFER_SIZE];
            try (InputStream in = source.getInputStream();
                 OutputStream out = target.getOutputStream()) {
                int bytesRead;
                while ((bytesRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesRead);
                    out.flush();
                }
            } catch (IOException e) {
                // 连接关闭
            }
        }
        private void cleanup(Socket socket) {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    // 忽略关闭异常
                }
            }
        }
    }
    /**
     * UDP转发处理类
     */
    private class UDPForwarder implements Runnable {
        private final DatagramSocket clientSocket;
        private final InetAddress clientAddress;
        private final int clientPort;
        private final InetAddress remoteAddress;
        private final int remotePort;
        public UDPForwarder(DatagramSocket clientSocket, 
                           InetAddress clientAddress, int clientPort,
                           InetAddress remoteAddress, int remotePort) {
            this.clientSocket = clientSocket;
            this.clientAddress = clientAddress;
            this.clientPort = clientPort;
            this.remoteAddress = remoteAddress;
            this.remotePort = remotePort;
        }
        @Override
        public void run() {
            try {
                // 创建远程Socket
                DatagramSocket remoteSocket = new DatagramSocket();
                remoteSocket.setSoTimeout(30000);
                byte[] buffer = new byte[UDP_BUFFER_SIZE];
                // 处理来自客户端的请求并转发到远程
                Thread requestThread = new Thread(() -> {
                    try {
                        while (true) {
                            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                            remoteSocket.receive(packet);
                            // 修改目标地址为客户端
                            packet.setAddress(clientAddress);
                            packet.setPort(clientPort);
                            clientSocket.send(packet);
                        }
                    } catch (SocketTimeoutException e) {
                        // 超时结束
                    } catch (IOException e) {
                        // 连接关闭
                    }
                });
                requestThread.start();
                // 处理来自远程的响应并转发到客户端
                while (true) {
                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                    clientSocket.receive(packet);
                    // 修改目标地址为远程服务器
                    packet.setAddress(remoteAddress);
                    packet.setPort(remotePort);
                    remoteSocket.send(packet);
                }
            } catch (IOException e) {
                // 异常处理
            }
        }
    }
    /**
     * 启动TCP端口转发
     */
    public void startTCPForwarding(int localPort, String remoteHost, int remotePort) throws IOException {
        ServerSocket serverSocket = new ServerSocket(localPort);
        System.out.println("TCP端口转发启动: localhost:" + localPort + " -> " + remoteHost + ":" + remotePort);
        while (true) {
            Socket clientSocket = serverSocket.accept();
            executorService.submit(new TCPForwarder(clientSocket, remoteHost, remotePort));
        }
    }
    /**
     * 启动UDP端口转发
     */
    public void startUDPForwarding(int localPort, String remoteHost, int remotePort) throws IOException {
        DatagramSocket socket = new DatagramSocket(localPort);
        InetAddress remoteAddress = InetAddress.getByName(remoteHost);
        System.out.println("UDP端口转发启动: localhost:" + localPort + " -> " + remoteHost + ":" + remotePort);
        byte[] buffer = new byte[UDP_BUFFER_SIZE];
        while (true) {
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
            socket.receive(packet);
            UDPForwarder forwarder = new UDPForwarder(
                socket,
                packet.getAddress(),
                packet.getPort(),
                remoteAddress,
                remotePort
            );
            executorService.submit(forwarder);
        }
    }
    /**
     * 获取当前活跃连接数
     */
    public int getActiveConnections() {
        return activeConnections.get();
    }
    /**
     * 关闭所有资源
     */
    public void shutdown() {
        executorService.shutdown();
    }
    public static void main(String[] args) {
        if (args.length < 4) {
            System.out.println("用法: java AdvancedPortForwarder <protocol> <localPort> <remoteHost> <remotePort>");
            System.out.println("示例: java AdvancedPortForwarder tcp 8080 www.example.com 80");
            return;
        }
        String protocol = args[0];
        int localPort = Integer.parseInt(args[1]);
        String remoteHost = args[2];
        int remotePort = Integer.parseInt(args[3]);
        AdvancedPortForwarder forwarder = new AdvancedPortForwarder();
        try {
            if ("tcp".equalsIgnoreCase(protocol)) {
                forwarder.startTCPForwarding(localPort, remoteHost, remotePort);
            } else if ("udp".equalsIgnoreCase(protocol)) {
                forwarder.startUDPForwarding(localPort, remoteHost, remotePort);
            } else {
                System.out.println("不支持的协议: " + protocol);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

高级版:带SSL支持和流量统计

import javax.net.ssl.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.KeyStore;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
public class SecurePortForwarder {
    private final ExecutorService executorService = Executors.newCachedThreadPool();
    private final Map<Integer, AtomicLong> trafficStats = new ConcurrentHashMap<>();
    // 流量统计类
    public static class TrafficInfo {
        private final long bytesTransferred;
        private final long connectionCount;
        public TrafficInfo(long bytesTransferred, long connectionCount) {
            this.bytesTransferred = bytesTransferred;
            this.connectionCount = connectionCount;
        }
        public long getBytesTransferred() {
            return bytesTransferred;
        }
        public long getConnectionCount() {
            return connectionCount;
        }
    }
    // 转发配置类
    public static class ForwardConfig {
        private final String localAddress;
        private final int localPort;
        private final String remoteHost;
        private final int remotePort;
        private final boolean sslEnabled;
        private final String keyStorePath;
        private final String keyStorePassword;
        public ForwardConfig(String localAddress, int localPort, 
                           String remoteHost, int remotePort,
                           boolean sslEnabled, String keyStorePath, 
                           String keyStorePassword) {
            this.localAddress = localAddress;
            this.localPort = localPort;
            this.remoteHost = remoteHost;
            this.remotePort = remotePort;
            this.sslEnabled = sslEnabled;
            this.keyStorePath = keyStorePath;
            this.keyStorePassword = keyStorePassword;
        }
    }
    public void startForwarding(ForwardConfig config) throws Exception {
        ServerSocket serverSocket;
        int port = config.localPort;
        if (config.sslEnabled) {
            // SSL配置
            SSLContext sslContext = createSSLContext(config);
            SSLServerSocketFactory factory = sslContext.getServerSocketFactory();
            SSLServerSocket sslServerSocket = (SSLServerSocket) factory.createServerSocket(port);
            sslServerSocket.setNeedClientAuth(false);
            serverSocket = sslServerSocket;
        } else {
            serverSocket = new ServerSocket(port);
            serverSocket.setReuseAddress(true);
        }
        System.out.println("Secure Port Forwarder 启动: " + 
                          config.localAddress + ":" + port + " -> " + 
                          config.remoteHost + ":" + config.remotePort);
        while (true) {
            Socket clientSocket = serverSocket.accept();
            executorService.submit(() -> handleConnection(clientSocket, config, serverSocket));
        }
    }
    private SSLContext createSSLContext(ForwardConfig config) throws Exception {
        KeyStore keyStore = KeyStore.getInstance("JKS");
        try (FileInputStream fis = new FileInputStream(config.keyStorePath)) {
            keyStore.load(fis, config.keyStorePassword.toCharArray());
        }
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(
            KeyManagerFactory.getDefaultAlgorithm()
        );
        kmf.init(keyStore, config.keyStorePassword.toCharArray());
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, null);
        return sslContext;
    }
    private void handleConnection(Socket clientSocket, ForwardConfig config, ServerSocket serverSocket) {
        Socket remoteSocket = null;
        String clientInfo = clientSocket.getInetAddress().getHostAddress() + ":" + clientSocket.getPort();
        try {
            // 记录连接
            trafficStats.computeIfAbsent(config.localPort, k -> new AtomicLong(0)).incrementAndGet();
            // 连接到远程服务器
            if (config.sslEnabled) {
                SSLContext context = SSLContext.getDefault();
                SSLSocketFactory factory = context.getSocketFactory();
                remoteSocket = factory.createSocket(config.remoteHost, config.remotePort);
            } else {
                remoteSocket = new Socket(config.remoteHost, config.remotePort);
            }
            // 设置TCP参数
            clientSocket.setTcpNoDelay(true);
            remoteSocket.setTcpNoDelay(true);
            System.out.println("新连接: " + clientInfo + " -> " + 
                              config.remoteHost + ":" + config.remotePort);
            // 创建两个方向的转发,并统计数据
            forwardWithStats(clientSocket, remoteSocket, config.localPort);
        } catch (IOException e) {
            System.out.println("连接处理错误: " + clientInfo + " - " + e.getMessage());
        } finally {
            cleanup(clientSocket);
            cleanup(remoteSocket);
        }
    }
    private void forwardWithStats(Socket source, Socket target, int port) {
        byte[] buffer = new byte[8192];
        AtomicLong bytesForwarded = trafficStats.get(port);
        try (InputStream in = source.getInputStream();
             OutputStream out = target.getOutputStream()) {
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
                out.flush();
                bytesForwarded.addAndGet(bytesRead);
            }
        } catch (IOException e) {
            // 连接关闭
        }
    }
    private boolean handleClientHello(Socket socket) {
        try {
            // 读取客户端数据来确定是否需要转发所有数据
            byte[] buffer = new byte[1024];
            InputStream inputStream = socket.getInputStream();
            // 只是为了演示,实际使用时可能需要更复杂的逻辑
            return inputStream.available() >= 0;
        } catch (IOException e) {
            return false;
        }
    }
    private void cleanup(Socket socket) {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                // 忽略
            }
        }
    }
    public TrafficInfo getTrafficInfo(int port) {
        AtomicLong stats = trafficStats.get(port);
        if (stats != null) {
            return new TrafficInfo(stats.get(), stats.longValue());
        }
        return new TrafficInfo(0, 0);
    }
    public void shutdown() {
        executorService.shutdownNow();
    }
    public static void main(String[] args) {
        SecurePortForwarder forwarder = new SecurePortForwarder();
        try {
            // 示例配置
            ForwardConfig config = new ForwardConfig(
                "localhost",           // 本地地址
                8080,                  // 本地端口
                "www.example.com",     // 远程主机
                80,                    // 远程端口
                false,                 // 不使用SSL
                null,                  // 密钥库路径
                null                   // 密钥库密码
            );
            // 启动转发
            forwarder.startForwarding(config);
            // 添加关闭钩子
            Runtime.getRuntime().addShutdownHook(new Thread(forwarder::shutdown));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用示例

// 使用简单版
public class PortForwardExample {
    public static void main(String[] args) {
        // 示例1: 将本机8080端口转发到远程80端口
        SimplePortForwarder forwarder1 = new SimplePortForwarder(
            "www.google.com", 80, 8080
        );
        try {
            forwarder1.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

命令行使用方式

# 编译
javac SimplePortForwarder.java
javac AdvancedPortForwarder.java
javac SecurePortForwarder.java
# 运行简单版
java SimplePortForwarder localhost 8080 80
# 运行高级版(TCP)
java AdvancedPortForwarder tcp 8080 www.example.com 80
# 运行高级版(UDP)
java AdvancedPortForwarder udp 5353 localhost 5353
# 运行安全版
java SecurePortForwarder

Maven依赖

<dependencies>
    <!-- 如果需要SSL支持 -->
    <dependency>
        <groupId>javax.net.ssl</groupId>
        <artifactId>javax.net.ssl-api</artifactId>
        <version>1.0.1</version>
    </dependency>
</dependencies>

关键特性说明

  1. 线程安全:使用ExecutorService管理线程池,避免线程泄漏
  2. 错误处理:完善的异常处理机制,确保资源正确释放
  3. 性能优化:设置TCP_NODELAY和SO_KEEPALIVE优化传输性能
  4. SSL支持:支持TLS/SSL加密传输(安全版)
  5. 流量统计:记录转发流量和连接数(安全版)
  6. 双向转发:支持客户端到服务器和服务器到客户端的双向数据传输

这个案例提供了从简单到复杂的多种端口转发实现,可以根据实际需求选择使用。

抱歉,评论功能暂时关闭!