UDP 打洞 java demo

UDP打洞的具体原理就不细说了文章还是很多,说下我的网络环境,家里台式电脑网线连的家里路由器(移动宽带),公司台式电脑网线连的公司路由器(电信宽带),一台有公网IP的华为云主机(我是试用一个月的)
1、华为云主机UDPServer代码

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.LinkedHashMap;

public class UDPServer {
    private static ArrayList<String> c = new ArrayList<String>();
    public static void main(String[] args) throws IOException, InterruptedException {
        DatagramSocket server = new DatagramSocket(9999);
        byte[] bytes = new byte[1024];
        while (true) {
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
            server.receive(packet);
            InetAddress address = packet.getAddress();
            int port = packet.getPort();
            String s = address.getHostAddress()+":"+port;
            System.out.println("收到->"+s+"的消息:");

            if (!c.contains(s)){
                c.add(s);
            }

            for (String s1 : c) {
                if (!s1.equals(s)){
                    byte[] b = ("this is server:"+s1).getBytes();
                    DatagramPacket packet1 = new DatagramPacket(b, b.length, address,port);
                    server.send(packet1);
                }
            }
        }
    }
}

2、公司台式电脑的UDPClient端代码

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

public class UDPClient {
    private static final ArrayList<String> c = new ArrayList<String>();
    private static boolean b=true;
    public static void main(String[] args) throws IOException, InterruptedException {
        DatagramSocket socket = new DatagramSocket();
        new Thread(()->{
            try {
                byte[] bytes = new byte[1024];
                DatagramPacket packet1 = new DatagramPacket(bytes, bytes.length);
                while (true){
                    socket.receive(packet1);
                    String receive = new String(bytes,0,packet1.getLength());
                    if (receive.contains("server")){
                        c.add(receive);
                    }
                    if (receive.contains("client")){
                        b = false;
                    }
                    System.out.println(receive);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

        byte[] data1 = "client:my is company".getBytes();
        while (true){
            if (b) {
                DatagramPacket packet1 = new DatagramPacket(data1, data1.length, InetAddress.getByName("121.36.221.82"),9999);
                socket.send(packet1);
            }
            if (!c.isEmpty()){
                DatagramPacket packet2 = new DatagramPacket(data1, data1.length, InetAddress.getByName(c.get(0).split(":")[1]), Integer.parseInt(c.get(0).split(":")[2]));
                socket.send(packet2);
            }
            TimeUnit.SECONDS.sleep(2);
        }
    }
}

3、家里的台电机和UDPClient的代码一样,修改sleep的时间为1秒,为了区分客户端发送的消息company可以改为family。121.36.21.88是我的华为云主机公网IP,代码也没有什么逻辑就没写注释,先启动Server,再启动两个客户端代码,如果客户端不停打印出my is company的提示说明打洞成功。成功后客户端不会再给Server发送消息,后面再贴Android的demo

上一篇:socket网络编程


下一篇:有限状态机 Spring StateMachine框架