udp 内网穿透 互发消息

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

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

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();
    }
    
}
View Code

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();

    }

}
View Code

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);
    }    
}
View Code

 

posted @ 2015-08-07 14:00  Bigben  阅读(299)  评论(0编辑  收藏  举报