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内网穿透 两个内网互联的更多相关文章

  1. 【网络】内网穿透方案&FRP内网穿透实战(基础版)

    目录 前言 方案 方案1:公网 方案2:第三方内网穿透软件 花生壳 cpolar 方案3:云服务器做反向代理 FRP简介 FRP资源 FRP原理 FRP配置教程之SSH 前期准备 服务器配置 下载FR ...

  2. frp内网 穿透映射使内网svn可外网访问

    起因 公司svn目前部署在内网服务器上,现在想在家中也可以使用,因此需要外网访问内网的工具 经过 使用过几个产品: utools,一个小巧的windows下的工具,内网映射只是它的一个小功能,支持tc ...

  3. 基于C#的内网穿透学习笔记(附源码)

    如何让两台处在不同内网的主机直接互连?你需要内网穿透!          上图是一个非完整版内外网通讯图由内网端先发起,内网设备192.168.1.2:6677发送数据到外网时候必须经过nat会转换成 ...

  4. QuantumTunnel:内网穿透服务设计

    背景 最近工作中有公网访问内网服务的需求,便了解了内网穿透相关的知识.发现原理和实现都不复杂,遂产生了设计一个内网穿透的想法. 名字想好了,就叫QuantumTunnel,量子隧道,名字来源于量子纠缠 ...

  5. frp 用于内网穿透的基本配置和使用

    frp 用于内网穿透的基本配置和使用 今天是端午节,先祝端午安康! frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP.UDP.HTTP.HTTPS 等多种协议.可以将内网服务以安全.便 ...

  6. 基于4G Cat.1的内网穿透实例分享

    上一篇分享了:小熊派4G开发板初体验 这一篇继续BearPi-4G开发板实践:内网穿透实验. 基本TCP的socket通信测试 之前我们学习WiFi模块时,与PC进行TCP协议的socket通信测试我 ...

  7. frp实现内网穿透

    frp实现内网穿透 目标 通过外网访问内网设备,本文中实现通过手机的移动流量,可以访问到树莓派设备 设备准备 需要被访问的设备(本文中使用Raspberry Pi`).公网IP设备(本文中使用阿里云 ...

  8. SSH 端口转发+内网穿透

    用最直白的语言对本文所有内容进行定义: 端口转发(-L):用A机器(内网)登录B机器(公网), 在A机器打开端口,将收到的所有请求转发到B机器的某个端口 (在代理机上执行) 内网穿透(-R):用A机器 ...

  9. SSH的内网穿透

    SSH的内网穿透 1.内网:     ssh -N -f -R 2222:127.0.0.1:22 lienzh@我的PC的IP2.外网:     ssh -p 2222 root@localhost ...

随机推荐

  1. mysqli预处理和事务处理

    1 应用环境 mysqli预处理功能(大量数据处理时使用) 2 步骤 a)mysqli连接数据库 $mysqli = new mysqli('localhost','root','root','chu ...

  2. iOS数据本地持久化

      p1:归档.Preference(NSUserDefault).沙盒存储 iOS开发中本地存储主要有三种形式 XML属性列表(plist)归档 Preference(偏好设置) NSKeyedAr ...

  3. Linux Linux程序练习七

    题目:实现两个程序mysignal.mycontrl,mycontrl给mysignal发送SIGINT信号,控制mysignal是否在屏幕打印“hello”字符串. //捕捉信号 #include ...

  4. Ajax实现异步操作实例_针对XML格式的请求数据

    js分类中有一节[原生js异步请求,XML解析]主要说明了js前台是如何处理XML格式请求和如何接受由服务器返回的XML数据的解析,今天我将用一个实例来说明具体要如何操作. 前台的参数类型也是XML使 ...

  5. pandas 修改 DataFrame 列名

    问题: 有一个DataFrame,列名为:['$a', '$b', '$c', '$d', '$e'] 现需要改为:['a', 'b', 'c', 'd', 'e'] 有何办法? import pan ...

  6. IOS开发之——reveal 的使用

    Reveal是一个iOS程序界面调试工具.使用Reveal,我们可以在iOS开发时动态地查看和修改应用程序的界面. 对于动态或复杂的交互界面,手写UI是不可避免的.通过Reveal,我们可以方便地调试 ...

  7. 20145222黄亚奇《Java程序设计》第6周学习总结

    教材学习内容总结 第十章 Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象. 从应用程序角度来看,如果要将数据从来源取出,可以使用输入串流,如果要将数据写入目的地,可以使用输 ...

  8. Hash中的一些概率计算

    Hash是把锋利的刀子,处理海量数据时经常用到,大家可能经常用hash,但hash的有些特点你是否想过.理解过.我们可以利用我们掌握的概率和期望的知识,来分析Hash中一些有趣的问题,比如: 平均每个 ...

  9. Sqlite3 设置插入触发器

    需求: 数据库中表t_VerifyCsmDetail需要最多保存10W条记录,超出时删除最旧的那一条. 思路:设置插入触发器.插入前先判断表中记录总数,如果大于99999条,则删除最旧的一条记录. 代 ...

  10. 嵌入式Linux驱动开发之helloword心得

    自从选择了物联网这个专业,智能XX的字样牵动着每一个学习这个专业的孩子. 大家兴致勃勃的来到了学校,结果一切想象和自己的设想并不一样.想象中的各种智能般梦幻的场景变成了真实的高数/电路/模电等等诸如此 ...