还差实现内网终端,向服务器发送请求,要对方的内网连接自己,实现打洞。在同一网段,或者公网运行,可以相互聊天。

没有实现检测客户端下线功能。

1,服务器代码

package router;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.HashSet;
import java.util.Set; public class Server {
// private Set<InetSocketAddress> clients= new HashSet();
DatagramSocket socket;
HeartBeat heart; Server(){
try {
socket = new DatagramSocket(9090);
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public void startServer(){
try { while(true){
byte[] buf = new byte[1024]; DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
InetAddress addr=packet.getAddress();
int port = packet.getPort(); InetSocketAddress address = new InetSocketAddress(addr,port);
heart.add(address);
send(heart.getDests(), address); String s = address + " is comming.";
notifyClients(s);
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
private void send(Object clients, SocketAddress client) throws IOException {
ByteArrayOutputStream bous = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bous);
oos.writeObject(clients);
oos.flush(); byte[] data= bous.toByteArray();
DatagramPacket sendip = new DatagramPacket(data, data.length);
sendip.setSocketAddress(client);
socket.send(sendip); } void notifyClients(String s){ for( SocketAddress client:heart.getDests()){
try {
send(s, client);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} public static void main(String[] args) {
Server server =new Server();
server.heart = new HeartBeat(server.socket);
server.startServer();
} }

2,客户端

package router;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.Set; import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField; public class Client extends Thread {
String serverip = "211.100.75.221";//"192.168.11.100";//
private SocketAddress server = new InetSocketAddress(serverip, 9090);
DatagramSocket socket; JTextArea jta_receive = new JTextArea(10, 50); JComboBox jta_addList = new JComboBox(); public Client() {
try {
socket = new DatagramSocket();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public void run() {
try { while (true) {
byte[] buf = new byte[1024]; DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
// log(new String(buf,buf.length));
read(packet.getData());
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } private void read(byte[] data) throws IOException, ClassNotFoundException {
ByteArrayInputStream bous = new ByteArrayInputStream(data);
ObjectInputStream oos = new ObjectInputStream(bous);
Object obj = oos.readObject(); if (obj instanceof Set) {
Set<InetSocketAddress> clients = (Set) obj;
jta_addList.removeAll();
jta_addList.removeAllItems(); for (InetSocketAddress it : clients) {
log(" add item:"+ it);
jta_addList.addItem(it);
}
}else if(obj instanceof String){
String ss =(String) obj;
if(!ss.startsWith("skip")){
jta_receive.append(ss);
jta_receive.append("\r\n");
}
}
}
void log(String s){
System.out.println(s);
}
void setUpUI() {
JFrame jf = new JFrame("p2p test");
jf.setLayout(new FlowLayout());
jf.setSize(700, 400); JButton jb_get = new JButton("get others ip");
jf.add(jb_get);
jf.add(jta_addList);
jb_get.addActionListener(new ActionListener() { @Override
public void actionPerformed(ActionEvent e) {
sendRequestMsg("getaddress"); } }); JLabel la_name = new JLabel("received:");
JLabel la_user = new JLabel("sendto:"); final JTextField jtf_send = new JTextField(20);
JButton bu_send = new JButton("send"); JScrollPane js = new JScrollPane(jta_receive); jf.add(la_name);
jf.add(js);
jf.add(la_user);
jf.add(jtf_send);
jf.add(bu_send); ActionListener sendListener = new ActionListener() { @Override
public void actionPerformed(ActionEvent e) {
String msg = jtf_send.getText();
InetSocketAddress dest = (InetSocketAddress) jta_addList
.getSelectedItem();
sendP2P(msg, dest);
jtf_send.setText("");
} }; bu_send.addActionListener(sendListener);
jtf_send.addActionListener(sendListener); jf.setVisible(true);
jf.setDefaultCloseOperation(3); } private void sendRequestMsg(String s) {
try {
byte[] buf = s.getBytes();
DatagramPacket packet; packet = new DatagramPacket(buf, buf.length, server); socket.send(packet); } catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} private void sendP2P(String msg, InetSocketAddress dest) {
try {
ByteArrayOutputStream bous = new ByteArrayOutputStream();
ObjectOutputStream oos;
oos = new ObjectOutputStream(bous); oos.writeObject(msg);
oos.flush(); byte[] data = bous.toByteArray();
DatagramPacket sendip = new DatagramPacket(data, data.length);
sendip.setSocketAddress(dest);
socket.send(sendip);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public static void main(String[] args) {
Client sender = new Client();
sender.start();
sender.setUpUI(); } }

3,心跳类

package router;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask; public class HeartBeat {
private static final long INTERVAL_TIME = 1 * 5 * 1000; private Timer timer;
static Set<SocketAddress> dests = new HashSet();
DatagramSocket socket;
public HeartBeat(DatagramSocket socket) {
this.socket = socket; 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() {
Set<SocketAddress> tmpDests = new HashSet<SocketAddress>();
byte[] b = "skip".getBytes(); // 发送心跳
println("====heartbeat====");
for (SocketAddress dest : dests) { println(dest.toString());
sendP2P("skip", dest);
// DatagramPacket packet = new DatagramPacket(b, b.length);
// packet.setSocketAddress(dest);
// socket.send(packet);
tmpDests.add(dest); }
dests = tmpDests;
}
} private void sendP2P(String msg, SocketAddress dest) {
try {
ByteArrayOutputStream bous = new ByteArrayOutputStream();
ObjectOutputStream oos;
oos = new ObjectOutputStream(bous); oos.writeObject(msg);
oos.flush(); byte[] data = bous.toByteArray();
DatagramPacket sendip = new DatagramPacket(data, data.length);
sendip.setSocketAddress(dest);
socket.send(sendip);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public void add(SocketAddress a){
dests.add(a);
}
public Set<SocketAddress> getDests() {
return dests;
} public void setDests(Set<SocketAddress> dests) {
this.dests = dests;
} SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd H:m:s"); public void println(String s) {
System.out.println(format.format(new Date()) + ": " + s);
}
}

udp 内网穿透 互发消息的更多相关文章

  1. udp内网穿透 两个内网互联

    1,在有外网ip的机器上启动server. package udp; import java.net.DatagramPacket; import java.net.InetSocketAddress ...

  2. UDP 内网穿透 心跳

    参考:http://blog.csdn.net/jacman/article/details/ 1: 启动一个Server. 2: 启动两个Client. 然后从Server端的Console里边可以 ...

  3. 内网穿透&UDP打洞

    这两天找度度重新回忆了一下关于内网穿透的事情,在百度文库上找到了两三篇写的比较通俗易懂的文章,把内网穿透做个简单总结. 首先文章建议 Cone NAPT 还有希望,要是 Symmetri NAPT 就 ...

  4. 手写内网穿透服务端客户端(NAT穿透)原理及实现

    Hello,I'm Shendi. 这天心血来潮,决定做一个内网穿透的软件. 用过花生壳等软件的就知道内网穿透是个啥,干嘛用的了. 我们如果有服务器(比如tomcat),实际上我们在电脑上开启了服务器 ...

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

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

  6. 使用FRP做内网穿透

    Github地址:https://github.com/fatedier/frp 什么是FRP? frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp 协议,为 http 和 h ...

  7. 一款带Web面板的轻量级、高性能内网穿透工具:nps使用教程

    说明:内网穿透工具之前已经介绍了不少了,比如Frp.lanproxy.Holer等,现在再介绍个带Web面板的穿透工具nps,之前叫easyProxy,只是改名了而已,该工具是一款使用go语言编写的轻 ...

  8. frp内网穿透学习

    前言 因为自己在内网,但是目标站在外网,这时候可以通过内网穿透工具,将接收到的请求转发到内网,实现在内网的msf可以控制外网的靶机. 也看了一些Ngrok,花生壳的,发现Ngrok.cc这个看文章说有 ...

  9. 如何使用 frp 实现内网穿透

    这有一个专注Gopher技术成长的开源项目「go home」 背景 作为一名程序员,家里多多少少会有一些落了灰的电脑,如果把闲置的电脑变成服务器,不仅有良好的配置,还能用来做各种测试,那就再好不过了. ...

随机推荐

  1. 搭建一个Web应用

    因为EasyUI会涉及到与后台数据的交互,所以使用Spring MVC作为后台,搭建一个完整的Web环境 使用gradle作为构建工具 build.gradle group 'org.zln.lkd' ...

  2. [py]编码 Unicode utf-8

    什么是字符集 在介绍字符集之前,我们先了解下为什么要有字符集.我们在计算机屏幕上看到的是实体化的文字,而在计算机存储介质中存放的实际是二进制的比特流.那么在这两者之间的转换规则就需要一个统一的标准,否 ...

  3. 浅谈VC++中预编译的头文件放那里的问题分析

    用C++写程序,肯定要用预编译头文件,就是那个stdafx.h.不过我一直以为只要在.cpp文件中包含stdafx.h 就使用了预编译头文件,其实不对.在VC++中,预编译头文件是指放到stdafx. ...

  4. Log4net Dll用法

    在导入Log4net的过程中,遇到一两个小bug. 开发平台必须是NET4 而不能是net4 client profile Log4Helper 里面的Namespace要和我们建立项目的名称一致. ...

  5. phpcms-v9视频模型的添加

    1.  下载化蝶自由飞插件http://www.phpcms.cn/show-90-8-1.html 下载回去后解压,覆盖 phpcms/ 和 statics/ 目录即可. 2.  执行一个sql语句 ...

  6. 一个Eclipse代码显示主题

  7. Linux第三次学习笔记

    #信息的表示和处理 三种重要的数字表示 1. 无符号数编码: 基于传统的二进制表示法,表示大于或者等于零的数字. 2. 补码编码: 表示有符号数整数的最常见的方式,有符号数就是只可 以为正或者为负的数 ...

  8. 一个js验证类

    //******************************************************************* //作者: 丁伯洋 //日期: 2006-4-27 //概要 ...

  9. BinaryWrite方法输出验证码

    在创建网站中验证码是不可或缺的.可以利用BinaryWrite输出二进制图像的方法输出验证码. 在开发图形验证码时,首先生成验证码,然后绘制成图像,最后通过该方法输出到页面中.所以熟练地掌握该方法可以 ...

  10. 远程办公《Remote》读书笔记:中国程序员在家上班月入过六万不是梦

    这不是一本新书,这是一本很值得中国程序员看的老书,所以我不是来做卖新书广告的:) 但它的确是一本好书,这本书在Amazon上3个business categories排第一.作者Jason Fried ...