本文目录导读:

我来提供一个完整的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>
关键特性说明
- 线程安全:使用ExecutorService管理线程池,避免线程泄漏
- 错误处理:完善的异常处理机制,确保资源正确释放
- 性能优化:设置TCP_NODELAY和SO_KEEPALIVE优化传输性能
- SSL支持:支持TLS/SSL加密传输(安全版)
- 流量统计:记录转发流量和连接数(安全版)
- 双向转发:支持客户端到服务器和服务器到客户端的双向数据传输
这个案例提供了从简单到复杂的多种端口转发实现,可以根据实际需求选择使用。