import java.net.*;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

public class udp {
    public static class GreeterServer extends Thread {
        private final AtomicBoolean asToStop = new AtomicBoolean(false);
        private static int port = 0;
        DatagramSocket socket = null;
        byte[] buf = new byte[256];

        public GreeterServer(int port_number, String name) throws SocketException {
            port = port_number;
            this.setName(name);
            this.start();
        }

        public void stopThread() {
            this.asToStop.set(true);
        }

        @Override
        public void run() {
            try {
                socket = new DatagramSocket(port);
            } catch (SocketException e) {
                throw new RuntimeException(e);
            }

            System.out.println("["+this.getName()+"] Listening on port "+ port +"...");

            while(!this.asToStop.get()) {
                DatagramPacket inPacket  = new DatagramPacket(buf, buf.length);
                try {
                    socket.receive(inPacket);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                String received = new String(inPacket.getData(), 0, inPacket.getLength());
                System.out.println("["+this.getName()+"] ["+inPacket.getAddress()+":"+inPacket.getPort()+"] " + received);

                if (received.equals("stop")) {
                    this.stopThread();
                    System.out.println("["+this.getName()+"] End listening");
                    continue;
                }

                InetAddress senderAddress = inPacket.getAddress();
                int senderPort = inPacket.getPort();
                DatagramPacket outPacket = new DatagramPacket(buf, buf.length, senderAddress, senderPort);
                try {
                    socket.send(outPacket);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

            socket.close();
        }
    }

    public static void sendName(String senderAddr, int senderPort, String name) throws IOException {
        byte[] buf = new byte[256];
        buf = name.getBytes();

        DatagramSocket socket = new DatagramSocket(12345);

        DatagramPacket inPacket  = new DatagramPacket(buf, buf.length);
        DatagramPacket outPacket = new DatagramPacket(buf, buf.length, InetAddress.getByName(senderAddr), senderPort);
        socket.send(outPacket);

        socket.close();
    }

    public static void main(String[] args) {
        GreeterServer server = null;
        try {
            server = new GreeterServer(25565, "Server1");
        } catch (SocketException e) {
            throw new RuntimeException(e);
        }

        try {
            sendName("127.0.0.1", 25565, "Le B");
            sendName("127.0.0.1", 25565, "Le C");
            sendName("127.0.0.1", 25565, "stop");
            sendName("127.0.0.1", 25565, "yo");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}