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」 背景 作为一名程序员,家里多多少少会有一些落了灰的电脑,如果把闲置的电脑变成服务器,不仅有良好的配置,还能用来做各种测试,那就再好不过了. ...
随机推荐
- Android service ( 二) 远程服务
通常每个应用程序都在它自己的进程内运行,但有时需要在进程间传递对象,你可以通过应用程序UI的方式写个运行在一个不同的进程中的service.在android平台中,一个进程通常不能访问其他进程中的内存 ...
- SpringMVC常用接收Json的两种方法
@RequestBody JSONObject requestJson @RequestBody User user 一种是自定义加注解,由Spring负责绑定,一种是使用通用的JSONObject
- 通过Nethogs查看服务器网卡流量情况
在日常运维工作中,会碰到服务器带宽飙升致使网站异常情况.作为运维人员,我们要能非常清楚地了解到服务器网卡的流量情况,观察到网卡的流量是由哪些程序在占用着. 今天介绍一款linux下查看服务器网卡流量占 ...
- ST3插件——PlainTasks的使用
今天看到一个有意思的ST3插件,可以进行简单的任务管理. 安装很简单:ctrl + shift + p,输入install回车,再输入plaintasks回车即可. 以下是一些支持的操作,更多的操作请 ...
- 各浏览器对typeof运算符的实现差异
1,IE6/7/8中typeof运算符对BOM对象如window,document,location,history等对象的方法返回“object”,标准浏览器都返回“function”. 1 2 3 ...
- ASP.NET MVC Razor HtmlHelper扩展和自定义控件
先看示例代码: using System; using System.Collections.Generic; using System.Linq; using System.Web; using S ...
- write_back 浅浅分析
hon@hon:~/f2fs$ grep -i "clearpagedirty" . -nr./mm/shmem.c:1240: ClearPageDirty(page);./mm ...
- eclipse系列: Cannot change version of project facet Dynamic web的解决方法
问题描述 用Eclipse创建Maven结构的web项目的时候选择了Artifact Id为maven-artchetype-webapp,由于这个catalog比较老,用的servl ...
- iOS适配HTTPS,创建一个自签名的SSL证书(x509)具体步骤
引言(创建生成的证书只能用于测试使用.如果想使用自签名证书就只能以自己为 CA机构颁发证书,进行双向认证才能使用) 使用HTTP(超文本传输)协议访问互联网上的数据是没有经过加密的.也就是说,任何人都 ...
- Sublime Text 之运行 ES6 (基于babel)
本文同步自我的个人博客:http://www.52cik.com/2015/10/21/sublime-text-run-es6.html 之前在博客园里写过一篇<Sublime Text 之运 ...