概述
Java使用Socket编写端口转发程序
Java使用Socket编写端口转发程序,程序如下:
1.编写Java类PortTransfer
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
public class PortTransfer extends Thread{
private static final int bufferSize = 8092;
private ServerSocket localServerSocket;
private int localPort ;
private String remoteHost ;
private int remotPort;
public static int soTimeOut = 300000;//5分钟超时
public static List<String> remoteHosts = Arrays.asList("192.168.60.133");
public static List<String> remotePorts = Arrays.asList("8899");
public static List<String> serverFrontPorts = Arrays.asList("18899");
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
if ("-remoteHosts".equals(args[i])) {
remoteHosts = Arrays.asList(args[i + 1].split(","));
i++;
} else if ("-serverFrontPorts".equals(args[i])) {
serverFrontPorts = Arrays.asList(args[i + 1].split(","));
i++;
} else if ("-remotePorts".equals(args[i])) {
remotePorts = Arrays.asList(args[i + 1].split(","));
i++;
}
}
for (int i = 0; i < remoteHosts.size(); i++) {
String remoteHost = remoteHosts.get(i);
int remotePort = Integer.parseInt(remotePorts.get(i));
int serverFrontPort = Integer.parseInt(serverFrontPorts.get(i));
new PortTransfer(serverFrontPort,remoteHost,remotePort).start();
}
}
public PortTransfer(int localPort,String remoteHost,int remotPort){
this.localPort = localPort;
this.remoteHost = remoteHost;
this.remotPort = remotPort;
}
public void run() {
try {
localServerSocket = new ServerSocket(localPort);
log("service started , listen on " +localServerSocket.getInetAddress().getHostAddress()+":"+ localPort + " , Remote:"+remoteHost+":"+remotPort);
// 一直监听,接收到新连接,则开启新线程去处理
while (true) {
Socket localSocket = localServerSocket.accept();
localSocket.setSoTimeout(soTimeOut); //5分钟内无数据传输、关闭链接
log(localSocket.getRemoteSocketAddress() + " conected");
new SocketThread(localSocket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private final static void log(Object message, Object... args) {
Date dat = new Date();
String msg = String.format("%1$tF %1$tT %2$-5s %3$s%n", dat, Thread.currentThread().getId(), String.format(message.toString(),args));
System.out.print(msg);
}
class SocketThread extends Thread{
private Socket localSocket;
private Socket remoteSocket;
private InputStream lin;
private InputStream rin;
private OutputStream lout;
private OutputStream rout;
public SocketThread(Socket socket) {
this.localSocket = socket;
}
public void run() {
try {
remoteSocket = new Socket();
remoteSocket.setSoTimeout(soTimeOut);//5分钟未收到数据,自动关闭资源
remoteSocket.connect(new InetSocketAddress(remoteHost, remotPort));
//设置超时,超过时间未收到客户端请求,关闭资源
remoteSocket.setSoTimeout(soTimeOut); //5分钟内无数据传输、关闭链接
rin = remoteSocket.getInputStream();
rout = remoteSocket.getOutputStream();
lin = localSocket.getInputStream();
lout = localSocket.getOutputStream();
new ReadThread().start();
//写数据,负责读取客户端发送过来的数据,转发给远程
byte[] data = new byte[bufferSize];
int len = 0;
while((len = lin.read(data)) > 0){
//System.out.println("------------>>>" + len);
if(len == bufferSize) {//读到了缓存大小一致的数据,不需要拷贝,直接使用
rout.write(data);
}else {//读到了比缓存大小的数据,需要拷贝到新数组然后再使用
byte[] dest = new byte[len];
System.arraycopy(data, 0, dest, 0, len);
rout.write(dest);
}
}
} catch (Exception e) {
//log(localSocket.getLocalAddress()+":"+localSocket.getPort() + " localSocket InputStream disconnected.");
}finally {
close();
}
}
//关闭资源
private void close(){
try {
if(remoteSocket !=null && !remoteSocket.isClosed()) {
remoteSocket.close();
log("remoteSocket>>>>" + remoteSocket.getRemoteSocketAddress() +" socket closed ");
}
} catch (IOException e1) {
e1.printStackTrace();
}
try {
if(localSocket !=null && !localSocket.isClosed()) {
localSocket.close();
log("localSocket>>>>" + localSocket.getRemoteSocketAddress() +" socket closed ");
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
//读数据线程负责读取远程数据后回写到客户端
class ReadThread extends Thread {
@Override
public void run() {
try {
byte[] data = new byte[bufferSize];
int len = 0;
while((len = rin.read(data)) > 0){
if(len == bufferSize) {//读到了缓存大小一致的数据,不需要拷贝,直接使用
lout.write(data);
}else {//读到了比缓存大小的数据,需要拷贝到新数组然后再使用
byte[] dest = new byte[len];
System.arraycopy(data, 0, dest, 0, len);
lout.write(dest);
}
}
} catch (IOException e) {
//log(remoteSocket.getLocalAddress() + ":"+ remoteSocket.getPort() + " remoteSocket InputStream disconnected.");
} finally {
close();
}
}
}
}
}
2.编绎后形成PortTransfer相关的class,编写start.bat测试脚本,将本地的3306的端口经由13306端口进行转发。
start.bat内容如下:
java PortTransfer -serverFrontPorts 13306 -remoteHosts 127.0.0.1 -remotePorts 3306
3.双击start.bat启动,进行测试
start.bat日志如下:
D:temp>java PortTransfer -serverFrontPorts 13306 -remoteHosts 127.0.0.1 -remotePorts 3306
2021-04-27 11:30:45 19 service started , listen on 0.0.0.0:13306 , Remote:127.0.0.1:3306
mysql -uroot -p123456 -P13306 -A
可看到通过13306端口能进行访问:
C:Usersjxlhl>mysql -uroot -p123456 -P13306 -A
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or g.
Your MySQL connection id is 2
Server version: 5.7.31 MySQL Community Server (GPL)
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
mysql>
最后
以上就是老迟到大雁为你收集整理的Java使用Socket编写端口转发程序的全部内容,希望文章能够帮你解决Java使用Socket编写端口转发程序所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复