还差实现内网终端,向服务器发送请求,要对方的内网连接自己,实现打洞。在同一网段,或者公网运行,可以相互聊天。
没有实现检测客户端下线功能。
1,服务器代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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,客户端
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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(" "); } } } 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,心跳类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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); } }