UDP 内网穿透 心跳
参考:http://blog.csdn.net/jacman/article/details/
1: 启动一个Server.
2: 启动两个Client.
然后从Server端的Console里边可以看到两个Client的NAT后的地址和端口。
在Server段输入命令 send:xxx.xxxx.xxx.xxx:xxxx
会给send后面的ip:port发送hello。
因为NAT 路由器一段时间会断开连接,我们就再也找不到内网的客户端了,所以需要心跳保持连接。
1,udp父类
package udp;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Pattern;
/**
*
* @author Leo Luo
*
*/
public class UDPAgent implements Runnable {
public static void main(String[] args) throws Exception {
new UDPAgent(-1).start();
}
DatagramSocket ds;
byte[] recbuf = new byte[1024];
DatagramPacket rec = new DatagramPacket(recbuf, recbuf.length);
static String ipPattern = "([0-9]{1,3}.){3}[0-9]{1,3}";
static String portPattern = "[0-9]{1,5}";
static Pattern sendPattern = Pattern.compile("send " + ipPattern + " "
+ portPattern + " .*");
int port;
public UDPAgent(int port) {
this.port = port;
}
public void init() throws Exception {
if (port < 1024 || port > 655535) {
ds = new DatagramSocket();
} else {
ds = new DatagramSocket(port);
}
println("====Address info======");
println("InetAddress.getLocalHost: " + InetAddress.getLocalHost());
println("connect getLocalPort:" + ds.getLocalPort());
println("getLocalAddress: " + ds.getLocalAddress().getHostAddress());
println("connect getPort:" + ds.getPort());
println("getInetAddress: " + ds.getInetAddress());
println("getLocalSocketAddress: " + ds.getLocalSocketAddress());
println("getRemoteSocketAddress: " + ds.getRemoteSocketAddress());
println("=======================");
}
public void start() throws Exception {
println("start");
println("LocalPort:" + port);
init();
new Thread(this).start();// recive thread
receive();
}
public void receive() {
for (;;) {
try {
// println("Waiting...");
ds.receive(rec);
String msg = new String(rec.getData(), rec.getOffset(),
rec.getLength());
if (msg.equals("skip"))
continue;
String line = "Received from " + rec.getSocketAddress()
+ ": [ " + msg + "]";
println(line);
onReceive(rec);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void onReceive(DatagramPacket rec) {
}
public void doCommand(String cmd) throws Exception {
// command:
// 1. send xxx.xxx.xxx.xxx xxx *******************
// if (sendPattern.matcher(cmd).matches()) {
if (cmd.startsWith("send")) {
doSend(cmd);
}
}
public void doSend(String cmd) throws Exception {
println("CMD: " + cmd);
String[] s = cmd.split(":", 4);
// println("===split cmd=========");
// for(String item:s){
// println(item);
// }
// println("============");
int port = Integer.parseInt(s[2]);
InetSocketAddress target = new InetSocketAddress(s[1], port);
byte[] bs = "Say Hello!".getBytes();
doSend(target, bs);
}
public void doSend(SocketAddress addr, byte[] data) throws Exception {
println("target:" + addr);
DatagramPacket pack = new DatagramPacket(data, data.length, addr);
ds.send(pack);
}
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
try {
String line = reader.readLine();
while (!"exit".equals(line)) {
doCommand(line);
line = reader.readLine();
}
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
}
}
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd H:m:s");
public void println(String s) {
System.out.println(format.format(new Date()) + ": " + s);
}
}
2,服务器端
package udp;
public class Server extends UDPAgent {
public static void main(String[] args) throws Exception {
new Server(2008).start();
}
public Server(int port) {
super(port);
}
}
3,客户端
package udp;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Timer;
import java.util.TimerTask;
public class Client extends UDPAgent {
private static final long INTERVAL_TIME = 1 * 20 * 1000;
SocketAddress server;
//
/**
* @param args
*/
public static void main(String[] args) throws Exception {
String ip = "211.100.75.221";
int serverPort = 2008;
if (args.length > 0) {
ip = args[0];
}
if (args.length > 1) {
serverPort = Integer.parseInt(args[1]);
}
new Client(ip, serverPort, -1).start();
}
public Client(String host, int port, int localPort) {
super(localPort);
this.server = new InetSocketAddress(host, port);
}
public void start() throws Exception {
println("start");
init();
register();
new Thread(this).start();// recive thread
new HeartBeat();
// dead loop
receive();
// Cannot reach here.
}
public void onReceive(DatagramPacket rec) {
try {
println("=== On Received ===");
report(rec);
if (rec.getSocketAddress().equals(server)) {
doCommand(new String(rec.getData(), rec.getOffset(),
rec.getLength()));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void report(DatagramPacket rec) throws Exception {
String s = " Server: " + rec.getSocketAddress() + " messgae:"
+ new String(rec.getData(), rec.getOffset(), rec.getLength());
byte[] buf = s.getBytes();
ds.send(new DatagramPacket(buf, buf.length, server));
}
public void register() throws Exception {
String msg = "register " + getLocalAddress() + " " + ds.getLocalPort();
doSend(server, msg.getBytes());
}
public String getLocalAddress() throws Exception {
InetAddress addr = InetAddress.getLocalHost();
return addr.getHostAddress();
}
class HeartBeat {
private Timer timer;
public HeartBeat() {
println("heartbeat start.");
try {
this.timer = new Timer();
this.timer.schedule(new ConnSvrTask(), 1000, INTERVAL_TIME);
} catch (Exception e) {
e.printStackTrace();
}
}
private class ConnSvrTask extends TimerTask {
public ConnSvrTask() {
super();
}
public void run() {
try {
byte[] b = "skip".getBytes();
DatagramPacket packet = new DatagramPacket(b, b.length);
// 发送心跳
// println("heartbeat");
packet.setSocketAddress(server);
ds.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
UDP 内网穿透 心跳的更多相关文章
- udp内网穿透 两个内网互联
1,在有外网ip的机器上启动server. package udp; import java.net.DatagramPacket; import java.net.InetSocketAddress ...
- udp 内网穿透 互发消息
还差实现内网终端,向服务器发送请求,要对方的内网连接自己,实现打洞.在同一网段,或者公网运行,可以相互聊天. 没有实现检测客户端下线功能. 1,服务器代码 package router; import ...
- 内网穿透&UDP打洞
这两天找度度重新回忆了一下关于内网穿透的事情,在百度文库上找到了两三篇写的比较通俗易懂的文章,把内网穿透做个简单总结. 首先文章建议 Cone NAPT 还有希望,要是 Symmetri NAPT 就 ...
- 手写内网穿透服务端客户端(NAT穿透)原理及实现
Hello,I'm Shendi. 这天心血来潮,决定做一个内网穿透的软件. 用过花生壳等软件的就知道内网穿透是个啥,干嘛用的了. 我们如果有服务器(比如tomcat),实际上我们在电脑上开启了服务器 ...
- 四、frp内网穿透服务端frps.ini各配置参数详解
[必须]标识头[common]是不可或缺的部分 [必须]服务器IPbind_addr = 0.0.0.00.0.0.0为服务器全局所有IP可用,假如你的服务器有多个IP则可以这样做,或者填写为指定其中 ...
- 使用FRP做内网穿透
Github地址:https://github.com/fatedier/frp 什么是FRP? frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp 协议,为 http 和 h ...
- 一款带Web面板的轻量级、高性能内网穿透工具:nps使用教程
说明:内网穿透工具之前已经介绍了不少了,比如Frp.lanproxy.Holer等,现在再介绍个带Web面板的穿透工具nps,之前叫easyProxy,只是改名了而已,该工具是一款使用go语言编写的轻 ...
- frp内网穿透学习
前言 因为自己在内网,但是目标站在外网,这时候可以通过内网穿透工具,将接收到的请求转发到内网,实现在内网的msf可以控制外网的靶机. 也看了一些Ngrok,花生壳的,发现Ngrok.cc这个看文章说有 ...
- 如何使用 frp 实现内网穿透
这有一个专注Gopher技术成长的开源项目「go home」 背景 作为一名程序员,家里多多少少会有一些落了灰的电脑,如果把闲置的电脑变成服务器,不仅有良好的配置,还能用来做各种测试,那就再好不过了. ...
随机推荐
- Http请求中POST与GET的区别——前端面试
一.原理区别 Http定义了与服务器交互的方法,其中最基本的四种是:GET,POST,PUT,DELETE,正对应着对资源的查,改,增,删.URL的全称是资源描述符,我们可以这样认为,一个URL地址, ...
- Linux Linux程序练习七
题目:实现两个程序mysignal.mycontrl,mycontrl给mysignal发送SIGINT信号,控制mysignal是否在屏幕打印“hello”字符串. //捕捉信号 #include ...
- OAF 使用 javascript 使某个按钮在5秒内不能重复点击
首先要保证按钮是BUTTON,并且按钮事件设置firePartialAction. public class CuxXXXXPGCO extends OAControllerImpl { public ...
- jQuery 遍历 - slice() 方法
实例 选中所有段落,然后将所选内容缩减为只包含第一和第二个段落: $("p").slice(0, 2).wrapInner(""); 亲自试一试 定义和用法 s ...
- Qt——QLineEdit使用总结
QLineEdit是一个单行文本编辑控件. 使用者可以通过很多函数,输入和编辑单行文本,比如撤销.恢复.剪切.粘贴以及拖放等. 通过改变QLineEdit的 echoMode() ,可以设置其属性,比 ...
- 设计传说 PS零基础精通 Photoshop CC 2015视频教程
课程目录: 课时1 Photoshop CC 2015 全面技能培训介绍 03:08课时2 1.1 PSCC工作区域及面板自定义 08:47课时3 1.2 图像文件的多种打开方式 0 ...
- 如何使用Iveely的数据存储引擎 Iveely Database
Iveely 数据存储引擎是为Iveely 搜索引擎提供数据存储的机制. 适用于:频繁数据插入.数据读取.数据更改或者删除数据不适合Iveely Database,存储结构是按照搜索引擎数据存储要求( ...
- 关于python中PIL的安装
python 的PIL安装是一件很蛋痛的事, 如果你要在python 中使用图型程序那怕只是将个图片从二进制流中存盘(例如使用Scrapy 爬网存图),那么都会使用到 PIL 这库,而这个库是出名的难 ...
- RVM 解决 Ruby 的版本问题
RVM 是一个命令行工具,可以提供一个便捷的多版本 Ruby 环境的管理和切换. RVM 的官网是 https://rvm.io/. 如果你打算学习 Ruby / Rails, RVM 是必不可少的工 ...
- Pell方程及其一般形式
一.Pell方程 形如x^2-dy^2=1的不定方程叫做Pell方程,其中d为正整数,则易得当d是完全平方数的时候这方程无正整数解,所以下面讨论d不是完全平方数的情况. 设Pell方程的最小正整数解为 ...