udp内网穿透 两个内网互联
1,在有外网ip的机器上启动server。
package udp; import java.net.DatagramPacket;
import java.net.InetSocketAddress; public class Server extends UDPAgent {
public static void main(String[] args) throws Exception {
new Server(2008).start();
} public Server(int port) {
super(port);
} public void onReceive(DatagramPacket rec) {
try {
println("=== Server OnReceive ===");
String s = rec.getSocketAddress().toString();
String msg = new String(rec.getData(), rec.getOffset(),
rec.getLength());
//if receive client's first log on, return its NAT port.
if (msg.trim().startsWith("register")) {
DatagramPacket outPacket = new DatagramPacket(s.getBytes(),
s.length(), rec.getSocketAddress());
// 发送数据 ds.send(outPacket);
}
} catch (Exception e) {
e.printStackTrace();
}
} public void doSend(String cmd) throws Exception {
println("====server's doSend=====");
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);
String msg = s[0]+" "+s[3];
doSend(target, msg.getBytes());
}
}
2,在内网启动2个client。
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("=== Client onReceive ==="); //if message not from server, then report to server.
// if (!rec.getSocketAddress().equals(server)) {
report(rec);//client should return status in order to tell server command execute result.
// } String receivedMsg = new String(rec.getData(), rec.getOffset(),
rec.getLength());
//if the received message is from server, do server's command.
if (rec.getSocketAddress().equals(server)) {
doCommand(receivedMsg);
}else{
println("Received from other client: "+receivedMsg);
} } catch (Exception e) {
e.printStackTrace();
}
} public void report(DatagramPacket rec) throws Exception {
String s = "Report: from " + rec.getSocketAddress() + " messgae:"
+ new String(rec.getData(), rec.getOffset(), rec.getLength());
byte[] buf = s.getBytes();
println("Report to server");
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();
} public void doSend(String cmd) throws Exception {
println("====client doSend=====");
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);
String msg = s[3];
doSend(target, msg.getBytes());
} 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();
}
}
}
}
}
3,他们共同的父类文件
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;
//skip heartbeat print out receive.
println("=== UDP Agent receive ===");
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);
}
}
在服务器端输入指令,根据连接上来的两个客户端ip:
send 192.168.11.100 57771 192.168.11.100 57768 message here
即让第一个客户端给第二个发送消息。
如果共同位于同一个nat后,ping不同彼此的ip。需要指定内网ip。服务器如何获取不知道。
udp内网穿透 两个内网互联的更多相关文章
- 【网络】内网穿透方案&FRP内网穿透实战(基础版)
目录 前言 方案 方案1:公网 方案2:第三方内网穿透软件 花生壳 cpolar 方案3:云服务器做反向代理 FRP简介 FRP资源 FRP原理 FRP配置教程之SSH 前期准备 服务器配置 下载FR ...
- frp内网 穿透映射使内网svn可外网访问
起因 公司svn目前部署在内网服务器上,现在想在家中也可以使用,因此需要外网访问内网的工具 经过 使用过几个产品: utools,一个小巧的windows下的工具,内网映射只是它的一个小功能,支持tc ...
- 基于C#的内网穿透学习笔记(附源码)
如何让两台处在不同内网的主机直接互连?你需要内网穿透! 上图是一个非完整版内外网通讯图由内网端先发起,内网设备192.168.1.2:6677发送数据到外网时候必须经过nat会转换成 ...
- QuantumTunnel:内网穿透服务设计
背景 最近工作中有公网访问内网服务的需求,便了解了内网穿透相关的知识.发现原理和实现都不复杂,遂产生了设计一个内网穿透的想法. 名字想好了,就叫QuantumTunnel,量子隧道,名字来源于量子纠缠 ...
- frp 用于内网穿透的基本配置和使用
frp 用于内网穿透的基本配置和使用 今天是端午节,先祝端午安康! frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP.UDP.HTTP.HTTPS 等多种协议.可以将内网服务以安全.便 ...
- 基于4G Cat.1的内网穿透实例分享
上一篇分享了:小熊派4G开发板初体验 这一篇继续BearPi-4G开发板实践:内网穿透实验. 基本TCP的socket通信测试 之前我们学习WiFi模块时,与PC进行TCP协议的socket通信测试我 ...
- frp实现内网穿透
frp实现内网穿透 目标 通过外网访问内网设备,本文中实现通过手机的移动流量,可以访问到树莓派设备 设备准备 需要被访问的设备(本文中使用Raspberry Pi`).公网IP设备(本文中使用阿里云 ...
- SSH 端口转发+内网穿透
用最直白的语言对本文所有内容进行定义: 端口转发(-L):用A机器(内网)登录B机器(公网), 在A机器打开端口,将收到的所有请求转发到B机器的某个端口 (在代理机上执行) 内网穿透(-R):用A机器 ...
- SSH的内网穿透
SSH的内网穿透 1.内网: ssh -N -f -R 2222:127.0.0.1:22 lienzh@我的PC的IP2.外网: ssh -p 2222 root@localhost ...
随机推荐
- C和指针笔记 3.6链接属性
链接属性决定如何处理在不同文件中出现的标识符.标识符的作用域也它的链接属性有关,但这两个属性并不相同. 没有链接属性的标识符(none)总是被当作单独的个体,也就是说该标识符的多个声明被当作独立不同的 ...
- Linq中查询List组合相同值数量大于1
List< select g.Key).ToList();
- [资料收集]MySQL在线DDL工具pt-online-schema-change
MySQL在线DDL工具pt-online-schema-change pt-online-schema-change使用说明(未完待续) 官网
- c语言 动态数组
C语言中,在声明数组时,必须明确告诉编译器数组的大小,之后编译器就会在内存中为该数组开辟固定大小的内存.有些时候,用户并不确定需要多大的内存,使用多大的数组,为了保险起见,有的用户采用定义一个大数组的 ...
- How to configure SRTM elevations in WorldWind WMS
In this thread I will try to explain how to serve SRTM elevations using NASA WorldWind WMS. ! Import ...
- 《认识你自己(Archetypes who are you?)》 10种原型的行为模式和性格特征
转自:http://www.cnblogs.com/richardcuick/p/5627298.html 拥护型原型 你自然而然地就会被社会.政治和环境问题所吸引. 你认为世界需要改变. 你承诺 ...
- LeetCode:Single Number II
题目地址:here 题目大意:一个整数数组中,只有一个数出现一次,其余数都出现3次,在O(n)时间,O(1)空间内找到这个出现一次的数 对于”只有一个数出现一次,其余数出现2次“的情况,很简单,只要把 ...
- 【iOS功能实现】之利用UIDocumentInteractionController打开和预览文档
iOS提供了使用其他app预览文件的支持,这就是Document Interaction Controller.此外,iOS也支持文件关联,允许其他程序调用你的app打开某种文件.而且,从4.2开始, ...
- 获取iOS系统版本 --- UIDevice
UIDevice类是一个单例,其唯一的实例( [UIDevice currentDevice] ) 代表了当前使用的设备. 通过这个实例,可以获得设备的相关信息(包括系统名称,版本号,设备模式等等). ...
- 《Java程序设计》第五次实验实验报告
实验封面 一.实验内容 1.阅读理解源码进入07_httpd所在的目录,使用vi编辑器理解源代码. 2.编译应用程序使用gcc编译器,分别对文件夹下的copy.c和httpd.c进行编译,出现copy ...