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

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

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

在服务器端输入指令,根据连接上来的两个客户端ip:

send 192.168.11.100 57771 192.168.11.100 57768 message here

即让第一个客户端给第二个发送消息。

如果共同位于同一个nat后,ping不同彼此的ip。需要指定内网ip。服务器如何获取不知道。

posted @ 2015-08-06 14:40  Bigben  阅读(692)  评论(0编辑  收藏  举报