为什么要转发,因为直接内网穿透在如今的架构已经无法实现了,比如说网上的nat穿透,现在内网出口的端口随机变得所以根本无法建立长连接。所以只能选择转发。
转发必备
- 必须有一台中间机器,必须有公网ip。
- 需要将客户端安装在内网。
简单转发原理以远程桌面3389为例
1.服务端建立服务端口10010
用远程桌面连接服务器的端口比如192.168.1.189:10010
这时候会有个socketclient连接到了服务端的10010,
服务端接收到客户端后,1.本地建立socket消息转发端口8080
2.然后本地建立客户端去建立客户端连接想转的端口比如3389
这个时候代码将 3389传回来的消息发给8080端口,然后8080端口收到消息后直接发给10010这样就实现了简单的转发了。
上Java代码
1.socket 中转类
package Tools;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TransPortData extends Thread {
Socket getDataSocket;
Socket putDataSocket;
String type;
public TransPortData(Socket getDataSocket, Socket putDataSocket, String type) {
this.getDataSocket = getDataSocket;
this.putDataSocket = putDataSocket;
this.type = type;
}
@Override
public void run() {
try {
System.out.println("被启动了");
InputStream in = getDataSocket.getInputStream();
OutputStream out = putDataSocket.getOutputStream();
Long lastTime = System.currentTimeMillis();
while (true) {
//读入数据
byte[] data = new byte[1024];
int readlen = in.read(data);
if (System.currentTimeMillis() - lastTime > 60000L) {
break;
}
if (getDataSocket.isClosed() || putDataSocket.isClosed()) {
break;
}
//如果没有数据,则暂停
if (readlen <= 0) {
Thread.sleep(300);
continue;
}
lastTime = System.currentTimeMillis();
out.write(data, 0, readlen);
out.flush();
}
} catch (Exception e) {
System.out.println("type:" + type);
e.printStackTrace();
} finally {
//关闭socket
try {
if (putDataSocket != null) {
putDataSocket.close();
}
} catch (Exception exx) {
}
try {
if (getDataSocket != null) {
getDataSocket.close();
}
} catch (Exception exx) {
}
}
}
}
2.常量类
package Tools;
public interface Constants {
// 服务端地址,支持IP或域名,这个根据服务端放的网络位置进行设置
String serviceIp = "127.0.0.1";
// 客户端服务的端口
int servicePort = 10010;
//中转端口
int transferPort = 8080;
//出口地址
String destIp = "192.168.101.29";
//出口端口
int destPort = 3389;
}
3.测试类
package simple;
import Tools.Constants;
import Tools.TransPortData;
import java.io.IOException;
import java.lang.reflect.Array;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.List;
public class ServerApp {
public static void main(String[] args) throws IOException {
ServerSocket socket=new ServerSocket(Constants.servicePort);
Socket clientSocket = null;
Socket remoteServerSocket = null;
System.out.println("服务器启动等待连接");
while(true){
try {
//获取客户端连接
clientSocket = socket.accept();
System.out.println("accept one client");
//建立远程连接
remoteServerSocket = new Socket(Constants.destIp, Constants.destPort);
System.out.println("create remoteip and port success");
//启动数据转换接口
(new TransPortData(clientSocket ,remoteServerSocket ,"1")).start();
(new TransPortData(remoteServerSocket ,clientSocket,"2")).start();
} catch (Exception ex) {
ex.printStackTrace();
}
//建立连接远程
}
}
}
上面是简单的转发,复杂的转发就是将连接的内容转到任意的机器,需要将server和client分离开。 server安装再公网机器,client安装在内网。
内网穿透原理从A穿透到B内网原理
0.B机器连接到公网server
1.A连接到 公网Server
2.公网Server 建立socket消息中转端口
2.公网Server将A的消息转给B
3.B在自己的机器上建立socket到指定端口 将消息返回给公网服务器的中专端口
4。公网Server中转端口收到消息后转发给A
以上就是复杂的消息转发。http好像还不行 http路径要其他考虑 复杂的没代码,写好了再传