对于网络用户来说,一定都经历过出门在外无法直接在异地访问公司的ERP系统、或是难以部署异地远程桌面,因此心急如焚的情况;对于企业来说,无论是财务管理软件难以将分店信息同步到总部进行统计汇总、还是员工出差在外或在家里就不能访问企业内部办公系统,都极大地影响了公司整体效率;对于个人开发者来说,微信小程序或者在线支付系统等开发环境往往需要一个可以环境进行调试,不然的话,难以进行开发调试。

诸如此类的难题众多,但解决方法其实很简单,那就是使用软件或者自己手写一个,可以支持访问我的电脑上的微信支付接口,从而实现这一系列的简易操作。目前国内这方面企业级的服务商有**壳和神卓互联,我接触过很多公司在用,**壳的技术是PHTunnel ,神卓互联用的是Wangooe Tunnel技术,这里就介绍神卓互联的,接下来就介绍和分析这款软件的用法和技术要点。如果没有接触过这方面技术的同学可以看一下这个图:

首先用法很简单,就是在界面上创建一条映射规则,填写应用名称和要连接的内网应用主机地址和端口号。

填写自己要穿透的应用名称和端口号,如果需要获取原访问者IP最好是选择Web应用。提交提交就可以了。

例如我需要发布一个Tomcat应用,访问端口号是7070,那么应用名称填写tomcat,内网主机填写127.0.0.1,内网端口填7070点提交就可以。

首先新建一个web项目

新建login.jsp登陆文件,内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录系统</title>
<style type="text/css">
table td{font: 14px/1.5 'Microsoft YaHei',arial,tahoma,\5b8b\4f53,sans-serif;}
</style>
</head>
<body>
<table>
<tr><td>用户名</td><td><input type="text"></td></tr>
<tr><td>密码</td><td><input type="text"></td></tr>
<tr><td>&nbsp;</td><td><input type="submit" value="登录"></td></tr>
</table>
</body>
</html>

先在本地运行,看项目是否可以正常运行

本地运行没有问题,可以正常打开,接下来就试一下外网访问

打开神卓互联软件主界面,右键选择外网访问

如果需要绑定域名访问的话也很简单,这里不多说。

接下来就分析是如何做到将请求转发到内网因为又返回给访问客户端的。

InetAddress

//获取本机的InetAddress实例
InetAddress address =InetAddress.getLocalHost();
address.getHostName();//获取计算机名
address.getHostAddress();//获取IP地址
byte[] bytes = address.getAddress();//获取字节数组形式的IP地址,以点分隔的四部分//获取其他主机的InetAddress实例
InetAddress address2 =InetAddress.getByName("其他主机名");
InetAddress address3 =InetAddress.getByName("IP地址");

URL类

//创建一个URL的实例
URL baidu =new URL("http://www.baidu.com");
URL url =new URL(baidu,"/index.html?username=tom#test");//?表示参数,#表示锚点
url.getProtocol();//获取协议
url.getHost();//获取主机
url.getPort();//如果没有指定端口号,根据协议不同使用默认端口。此时getPort()方法的返回值为 -1
url.getPath();//获取文件路径
url.getFile();//文件名,包括文件路径+参数
url.getRef();//相对路径,就是锚点,即#号后面的内容
url.getQuery();//查询字符串,即参数

以下就是P2P打洞核心代码(TCP)

假设现在有以下3台机器:

外网机器,IP:121.56.21.85 , 以下简称“主机A”

处在内网1下的机器,外网IP:106.116.5.45 ,内网IP:192.168.1.10, 以下简称“主机1”

处在内网2下的机器,外网IP:104.128.52.6 ,内网IP:192.168.0.11,以下简称“主机2”

很显然内网的两台机器不能直接连接,我们现在要实现的是借助外网机器,让两台内网机器进行tcp直连通讯。

实现过程如下:

1、主机A启动服务端程序,监听端口8888,接受TCP请求。

2、启动主机1的客户端程序,连接主机A的8888端口,建立TCP连接。

3、启动主机2的客户端程序,连接主机A的8888端口,建立TCP连接。

4、主机2发送一个命令告诉主机A,我要求与其他设备进行连接,请求协助进行穿透。

5、主机A接收到主机2的命令之后,会返回主机1的外网地址和端口给主机2,同时把主机2的外网地址和端口发送给主机1。

6、主机1和主机2在收到主机A的信息之后,同时异步发起对对方的连接。

7、在与对方发起连接之后,监听本地与主机A连接的端口(也可以在发起连接之前),(由于不同的操作系统对tcp的实现不尽相同,有的操作系统会在连接发送之后,把对方的连接当作是回应,即发出SYN之后,把对方发来的SYN当作是本次SYN的ACK,这种情况就不需要监听也可建立连接,本文的代码所在测试环境就不需要监听,测试环境为:服务器centos 7.3, 内网1 win10,内网2 win10和centos7.2都测试过)。

8、主机1和主机2成功连上,可以关闭主机A的服务,主机1和主机2的连接依然会持续生效,不关闭就形成了一个3方直连的拓扑网状结构网络。

服务器端代码:

package org.inchain.p2p;import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;/*** 外网端服务,穿透中继* * @author ln**/
public class Server {public static List<ServerThread> connections = new ArrayList<ServerThread>();public static void main(String[] args) {try {// 1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口ServerSocket serverSocket = new ServerSocket(8888);Socket socket = null;// 记录客户端的数量int count = 0;System.out.println("***服务器即将启动,等待客户端的连接***");// 循环监听等待客户端的连接while (true) {// 调用accept()方法开始监听,等待客户端的连接socket = serverSocket.accept();// 创建一个新的线程ServerThread serverThread = new ServerThread(socket);// 启动线程serverThread.start();connections.add(serverThread);count++;// 统计客户端的数量System.out.println("客户端的数量:" + count);}} catch (IOException e) {e.printStackTrace();}}
}
package org.inchain.p2p;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;/*** 外网端服务多线程处理内网端连接* * @author ln**/
public class ServerThread extends Thread {// 和本线程相关的Socketprivate Socket socket = null;private BufferedReader br = null;private PrintWriter pw = null;public ServerThread(Socket socket) throws IOException {this.socket = socket;this.br = new BufferedReader(new InputStreamReader(socket.getInputStream()));this.pw = new PrintWriter(socket.getOutputStream());}// 线程执行的操作,响应客户端的请求public void run() {InetAddress address = socket.getInetAddress();System.out.println("新连接,客户端的IP:" + address.getHostAddress() + " ,端口:" + socket.getPort());try {pw.write("已有客户端列表:" + Server.connections + "\n");// 获取输入流,并读取客户端信息String info = null;while ((info = br.readLine()) != null) {// 循环读取客户端的信息System.out.println("我是服务器,客户端说:" + info);if (info.startsWith("newConn_")) {//接收到穿透消息,通知目标节点String[] infos = info.split("_");//目标节点的外网ip地址String ip = infos[1];//目标节点的外网端口String port = infos[2];System.out.println("打洞到 " + ip + ":" + port);for (ServerThread server : Server.connections) {if (server.socket.getInetAddress().getHostAddress().equals(ip)&& server.socket.getPort() == Integer.parseInt(port)) {//发送命令通知目标节点进行穿透连接server.pw.write("autoConn_" + socket.getInetAddress().getHostAddress() + "_" + socket.getPort()+ "\n");server.pw.flush();break;}}} else {// 获取输出流,响应客户端的请求pw.write("欢迎您!" + info + "\n");// 调用flush()方法将缓冲输出pw.flush();}}} catch (Exception e) {e.printStackTrace();} finally {System.out.println("客户端关闭:" + address.getHostAddress() + " ,端口:" + socket.getPort());Server.connections.remove(this);// 关闭资源try {if (pw != null) {pw.close();}if (br != null) {br.close();}if (socket != null) {socket.close();}} catch (IOException e) {e.printStackTrace();}}}@Overridepublic String toString() {return "ServerThread [socket=" + socket + "]";}
}

最后附上测试方法和运行效果:

使用方法:
1、在服务器启动Server。
2、在客户端1启动Client,输入notwait命令,等待服务器通知打洞。
3、在客户端2启动Client,输入conn命令,然后输入服务器返回的客户端1的外网ip和端口,接下来就会自动完成连接。
运行效果:
客户端1运行结果 (穿透成功之后,客户端会把穿透对方返回的内容发送给服务器,服务器再返回)

客户端1使用netstat查看的网络连接

客户端2的运行结果

客户端2使用netstat查看的网络连接

可以看到客户端2对应的端口不同,那是因为电信NAT的问题,本地获取的Ip是电信10开头的内网地址,相当于在客户端2的上层还进行了一次中继。

s:由于没有对称型的NAT设备,无法做深入研究,对称型设备的端口太难猜测,穿透成功概率很小。

永久免费内网穿透很简单,一看就明白(长文)相关推荐

  1. 五种永久免费 内网穿透傻瓜式使用

    多种永久免费 内网穿透傻瓜式使用 教程 方法一(使用qydev) 方法二(使用飞鸽内网穿透) 方法三(使用nps) 方法四使用 (神卓互联内网穿透) 方法五 使用 SAKURA FRP 方法六 使用 ...

  2. 永久免费 内网穿透工具 傻瓜式配置

    永久免费 内网穿透工具   傻瓜式配置 使用教程 配合工具:网云穿 先官网注册:点击访问注册 1.进入官网首页,点击右上方注册 2.注册后,我们在官网领取隧道 3.领取完隧道会直接让我们跳转控制台,配 ...

  3. 几款永久免费内网穿透,好用且简单

    几款免费内网穿透工具小结 实际工作和生活中,常常遇到以下问题:如何让任何地方都能访问自己家里的笔记本上的应用?如何让局域网的服务器可以被任何地方访问到?如何在异地远程处理公司服务问题:企业员工如何在异 ...

  4. 永久免费内网穿透不限制速度

    市面上的免费内网穿透大都有格式各样的限制,什么限制流量啊,每个月要签到打卡啊,还有更改域名地址等,只有神卓互联内网穿透是永久免费没有限制的,白嫖也可以. 这篇文章分享了3个方案,按照性能和综合指标排序 ...

  5. 什么是内网穿透技术?简单实用、永久免费内网穿透工具有哪些?

    内网穿透即是内网映射,内网(IP)端口映射外网(IP或域名),以实现将内网服务器.网站.和应用发布到外网访问的目的.通常在内网网络环境搭建服务器(解决无公网IP问题),需要外网访问内网场景(如远程办公 ...

  6. (不打广告)推荐这款永久免费内网穿透软件-神卓互联

    内网穿透是一种将内部网络中的应用程序公开到公共网络上的技术.在许多情况下,由于网络安全限制或配置问题,内部网络中的应用程序可能无法通过公共网络访问.这时,内网穿透技术就可以解决这个问题,使得我们可以在 ...

  7. 无需设置路由器,无需公网ip 实现永久免费内网穿透

    用网云穿在 N1 盒子上实现 Openwrt 的内网穿透 软路由器情况 N1(已经刷入 Armbian) 中使用 docker 创建 Openwrt 容器作为旁路由. 我的内网 ip 信息 内网 IP ...

  8. 简单免费内网穿透教程,利用树莓派实现低成本建站 无需公网

    很多人都想试试自己建站玩一玩 (比如博客.自建网盘.远程下载等),但家里宽带没公网 IP,特意买台服务器又显得浪费.那么有没成本小.可玩性高.又能长期稳定使用的方案呢? 其实,免费的内网穿透工具 (如 ...

  9. 内网穿透的作用 免费内网穿透有哪些 可以用来干什么

    相信有很多人都会被一个问题所困惑,我们在日常办公和生活中:一些内网访问的应用,如何让实现在任意外网进行链接访问呢?有人说可以用内网穿透 内网穿透具体是什么,原理是什么:今天我们用网云穿来做演示.内网穿 ...

最新文章

  1. MVC (ModelBinder等)技巧
  2. MySQL数据表的创建、查看、插入
  3. qt程序在Linux下字体乱了,解决linux/Ubuntu下Qt creater 界面程序在编译运行后无法显示中文或中文乱码问题!...
  4. c语言抓取机器硬件阐述,c语言如何控制硬件
  5. mysql左右连接举例_MYSQL 连接举例
  6. Filter过滤器拦截方式
  7. Job单线程运行的方案
  8. 1. PSR-1 --- 基本代码规范
  9. 利用struts2上传文件时,如果文件名中含有-符号,那么会出错
  10. 服务器ipsan虚拟化,挂载IPSAN存储+链接克隆模板(修正版)
  11. 利用wePE制作WinPE启动U盘全过程(含图文)
  12. Android中将像素转换为sp/dp
  13. php留言板的实验步骤,PHP实现基本留言板功能原理与步骤详解
  14. Google Voice 虚拟号码
  15. 为啥用计算机分析模拟,计算机模拟的优缺点及应用分析
  16. 【计算机图形学】【OpenGL】基于窗口的Liang-Barsky的折线段裁剪的实现
  17. iOS常用快捷键/终端常用指令
  18. 请更换备份电池 pos机_什么pos机刷信用卡最好最安全,不会跳码最稳定
  19. 百科知识 天气图标示例
  20. 一文掌握需求评审常见难题及改进策略【一杯咖啡谈项目】

热门文章

  1. 宝宝为什么经常拉肚子?
  2. HDU - 4737 A Bit Fun 暴力水题
  3. APT - Advanced Package Tool
  4. error: Failed dependencies:
  5. 报错:Error querying database. Cause: java.sql.SQLException: Access denied for user ‘root‘@‘localhost‘
  6. 使用Chrome开发者工具调用REST接口(附图)
  7. 教你如何用android系统通过Remote Desktop远程控制电脑
  8. 基于vue 在平面图上画路线图 canvas
  9. Ubuntu Linux 3D桌面完全教程(转贴)
  10. Perl:化繁为简 (转载)